验证与授权

Authentication(身份认证)

认证是系统对请求的用户进行身份识别的过程。

Authorization (授权)

授权是对认证通过后的用户进行权限分配的过程。授权简单理解就是:识别认证后用户所拥有哪些权限,从而开放服务器相对应的资源;

我们通俗点来解释身份验证与授权:验证确认用户是否允许访问,授权给予登录后的用户指定权限标识(通过这个标识,服务端可允许用户进行访问和操作);

在进行讲解Jwt身份认证前我们来回一下过去我们在MVC、WebForm这些站点都是怎样进行身份认证的。

我想应该大多数都是基于Cookie、Form表单的身份验证方式吧。

Cookie验证方式的流程图如下:

上面流程就是服务端在接收用户登录请求后创建Cookie并保存在服务器上,然后通过Response.Cookies.Add将Cookie返回客户端。

客户端浏览器可以记住服务器返回的Cookie,记住后Cookie值会存储在客户端硬盘上,下次访问站点时候Http请求头会携带Cookie。

携带Cookie的请求到服务端后,服务端进行验证,验证通过后即可正返回请求的资源,否则会跳转到登录页面。

Cookie方式的缺点

了解到Cookie方式的验证流程后可以发现它是对Http请求强加了一层“会话”,让我们的Http请求携带与身份认证相关的标识(Cookie)。

那这种方式有什么不好的呢?我总结了下面几点:

1、对有多种客户端(APP、浏览器、Winform应用)请求的场景不好扩展;
2、对分布式架构的服务端不好扩展,客户端的请求不一定指向同一台服务器,每一台服务器都需存储针对已登录的用户Cookie;
3、跨域访问问题;

Jwt身份验证方式

在多终端,分布式架构的服务无所不在的今天,Cookie身份认证的方式显然是难以满足我们的,这个时候Jwt(Json Web Token)横空出世啦~

使用Jwt我们可以完美的解决上面的遗留问题(当然后面也会说到jwt本身存在的问题....)

我们先看下Jwt的身份验证流程:

根据流程图得知jwt是在返回Token给客户端后要求客户端在Http请求头里携带载有Jwt信息的Authorization对象。

服务端会通过密钥对Jwt信息进行解密和验证,验证通过后会返回客户端所请求的资源。

根据流程我们得知jwt至少依赖这几项:

1、服务端的密钥;

2、客户端请求需指定格式(请求头携带Token);

其中密钥是客户端接触不到的,客户端所拥有的其实就是服务端生成的Token,这个Token是由三部分组成:

1、Header(包含算法和Token的类型:jwt)

2、PayLoad(负载,可配置的一些标识数据,不要将敏感信息写入到PayLoad内)

3、验签

其中Header和PayLoad只是在服务端进行了base64转码,所以如果有人抓取了Http请求是可以轻易截取里面的数据,我们

使用过程中千万不要将一些敏感信息放置里面。想详细了解Jwt信息可以到官网看看,官网地址:https://jwt.io/

.Net Core进行Jwt身份认证

.NetCore上使用Jwt身份认证非常简单,我们在Startup.cs文件的ConfigureServices里加入以下代码:

   services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
//获取权限是否需要HTTPS
x.RequireHttpsMetadata = false;
//在成功的授权之后令牌是否应该存储在Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties中
x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters
{
//是否验证秘钥
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});

在Startup里的Configure方法必须添加下面这行代码,且要求写在 app.UseMvc();前面。

app.UseAuthentication(); //引用身份认证服务

上面的关键代码是Startup里的代码。 它明确告知系统采取Jwt验证方式为默认的身份认证方式、秘钥的

生成方式,以及一些验证相关的参数配置。

OK,现在我们已经明确了验证方式了,那我们创建Token是在哪里创建的呢?

我们来看看下面代码:

         private TokenDto CreateToken(User user)
{
// JwtSecurityTokenHandler可以创建Token
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
DateTime tokenExpires = DateTime.Now.AddMinutes(); //过期时间这里写死
DateTime refRefreshTokenExpires = tokenExpires.AddMinutes(-);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
//添加申明,申明可以自定义,可以无限扩展,对于后续的身份验证通过后的授权特别有用...
new Claim(ClaimTypes.Name, user.Id.ToString()),
new Claim("refRefreshTokenExpires",refRefreshTokenExpires.ToString()),
new Claim("tokenExpires",tokenExpires.ToString())
}),
Expires = tokenExpires,
IssuedAt = DateTime.Now, //Token发布时间
Audience = "AuthTest", //接收令牌的受众
//根据配置文件的私钥值设置Token
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
user.Token = tokenHandler.WriteToken(token);
TokenDto output = Mapper.Map<TokenDto>(user);
output.RefRefreshToken = Guid.NewGuid().ToString();
output.RefRefreshTokenExpires = refRefreshTokenExpires.ToString("yyyy-MM-dd HH:mm:ss");
output.Token = user.Token;
UserRefreshTokenData(user, output);
return output;
}

上面代码是包含了 刷新Token和刷新Token时间的创建Token方法。

我在验证用户账号密码正确后即调用上面方法将Token返回给客户端,要求客户端在后续的API里必须携带Token来进行访问。

Token的有效时间我在上面写死了为三分钟,即三分钟后访问需授权的接口都会报http响应码为401的错误,如果需要解决则

要求客户端在刷新时间内,携带刷新Token值、刷新时间来调用 刷新Token接口获取 刷新后的Token值。

刷新Token方法;

    public TokenDto RefreshToken(TokenDto oldTokenDto)
{
TokenDto output = new TokenDto();
//如果有刷新Token值对应的用户则刷新Token以及RefRefreshToken
var user = _users.FirstOrDefault(p => p.RefRefreshToken == oldTokenDto.RefRefreshToken
&& Convert.ToDateTime(oldTokenDto.RefRefreshTokenExpires) > DateTime.Now);
if (user != null)
{
output = CreateToken(user);
}
return output;
}

至此,.NetCore采取JWT验证身份方式就写好了,包含了刷新Token。

对了,还没有总结JWT的劣势,劣势我捋了下面几点:

1、没有一个很方便的撤销已颁发的JWT令牌方法;

2、续签(刷新Token)增加了客户端的工作量(需要客户端在请求前验证刷新Token时间);

3、Token的加密与解密是与开发者自定义的payload的大小有关,如果存储的东西越多自然执行的效率也会越低(建议存储少量信息);

不过上面问题也不大,撤销令牌可以采取黑名单方式,至于第2点其实问题可以与前端约定好流程即可;

.NetCore采取JWT方式进行身份认证的更多相关文章

  1. PHP 使用 jwt 方式用户身份认证

    封装类 // +---------------------------------------------------------------------- // | Created by PhpSt ...

  2. .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger)

    上接:.NetCore WebApi——Swagger简单配置 任何项目都有权限这一关键部分.比如我们有许多接口.有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问:以保证重要数据不会泄露 ...

  3. ASP.NET Web API 2系列(四):基于JWT的token身份认证方案

    1.引言 通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证.验证方式非常多,本 ...

  4. 基于JWT的token身份认证方案

    一.使用JSON Web Token的好处? 1.性能问题. JWT方式将用户状态分散到了客户端中,相比于session,可以明显减轻服务端的内存压力. Session方式存储用户id的最大弊病在于S ...

  5. 基于JWT的token身份认证方案(转)

    https://www.cnblogs.com/xiangkejin/archive/2018/05/08/9011119.html 一.使用JSON Web Token的好处? 1.性能问题. JW ...

  6. 身份认证防止重放攻击的challenge-response方法

    或者叫询问-应答机制. 基于挑战/应答(Challenge/Response)方式的身份认证系统就是每次认证时认证服务器端都给客户端发送一个不同的"挑战"字串,客户端程序收到这个& ...

  7. 【译】使用Jwt身份认证保护 Asp.Net Core Web Api

    原文出自Rui Figueiredo的博客,原文链接<Secure a Web Api in ASP.NET Core> 摘要:这边文章阐述了如何使用 Json Web Token (Jw ...

  8. spring jwt springboot RESTful API认证方式

    RESTful API认证方式 一般来讲,对于RESTful API都会有认证(Authentication)和授权(Authorization)过程,保证API的安全性. Authenticatio ...

  9. springboot结合jwt实现基于restful接口的身份认证

    基于restful接口的身份认证,可以采用jwt的方式实现,想了解jwt,可以查询相关资料,这里不做介绍~ 下面直接看如何实现 1.首先添加jwt的jar包,pom.xml中添加依赖包: <de ...

随机推荐

  1. BZOJ_1026_[SCOI2009]windy数_数位DP

    BZOJ_1026_[SCOI2009]windy数_数位DP 题意:windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之 ...

  2. BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法

    BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ...

  3. SQL Server 中如何做到连续时间段的拆分?

    今天在工作中遇到了一个很实际的问题,客户在OA接口的员工休假中间表中提供了连续时间段的休假记录,例如: 张三,2018-12-1 ~2018-12-31 ,病假,31天.这样带来的问题是,如果我需要统 ...

  4. Java Applet 与Servlet之间的通信

    1 Applet对Servlet的访问及参数传递的实现 2.1.1创建URL对象 在JAVA程序中,可以利用如下的形式创建URL对象 URL servletURL = new URL( "h ...

  5. 从壹开始前后端分离【 .NETCore2.1 +Vue 2 +AOP+DI】框架之一 || 前言

    缘起 作为一个.Net攻城狮已经4年有余了,一直不温不火,正好近来项目不是很忙,闲得无聊,搞一搞新技术,一方面是打发无聊的时间,一方面也是督促自己该学习辣!身边的大神都转行的转行,加薪的加薪,本人比较 ...

  6. ASP.NET Core 实战:使用 Docker 容器化部署 ASP.NET Core + MySQL + Nginx

    一.前言 在之前的文章(ASP.NET Core 实战:Linux 小白的 .NET Core 部署之路)中,我介绍了如何在 Linux 环境中安装 .NET Core SDK / .NET Core ...

  7. PHP 单例模式优点意义及如何实现

    一.什么是单例模式? 1.含义 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. 2. ...

  8. vue3+typescript引入外部文件

    vue3+typescript中引入外部文件有几种方法 (eg:引入echarts) 第一种方法: 1 indext.html中用script引入 <div id="app" ...

  9. Vue.js 学习笔记 第6章 表单与v-model

    本篇目录: 6.1 基本用法 6.2 绑定值 6.3 修饰符 表单类控件承载了一个网页数据的录入与交互,本章将介绍如何使用指令v-model完成表单的数据双向绑定. 6.1 基本用法 表单控件在实际业 ...

  10. CSS引入本地字体与在线字体

    有些时候为了强调某些文字,需要使用一些比较特别的字体,CSS中现在也可以比较方便的引入字体了,如下: /* 定义字体 */ @font-face{ font-family: Arista2; src: ...