我们最常用的认证系统是Cookie认证,通常用一般需要人工登录的系统,用户访问授权范围的url时,会自动Redirect到Account/Login,登录后把认证结果存在cookie里。

系统只要找到这个cookie就认为这个web用户是已经登录的了。

通常的代码段是这样的,StartUp.cs

services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie();
public async Task<IActionResult> Login(IFormCollection form)
{
string userName = form["txtLoginId"];
string pwd = form["txtPwd"];
if (Validate(userName, pwd))
{
var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, userName) }, "Basic");
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
return Json(new { isSuccess = true, message = "登录成功" });
} }

如果我们用RestFul API写接口给前端或第三方程序使用时,这种重定向登录的方式就不合适了。

最合适的方法是,前端访问一个Login接口,获得一个AccessToken,然后用这个Token去访问后端的资源, 后端验证这个token的正确性,就放行让前端访问。

一开始比较笨的方法,是在每个接口方法都加一个accessToken的字段,这样不够优雅,可以把这个token放在Header里。这就是JWT认证

JWT有什么好处?

1、支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.

2、无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.

4、更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服务端只要提供API即可.

5、去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.

6、更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。

7、CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。

8、性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多.

9、不需要为登录页面做特殊处理

10、基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库和多家公司的支持.

JWT是用于验证而非加密,任何人即使没有密钥secret,header与payload中的数据都是可以获取的。
使用 jwt.io,可以进行JWT的编码、解码和验证
.net Core 使用Jwt认证的方法

1. 在startup.cs 的configureService 方法里注册JWT Authetication,为Swagger增加JWT Auth支持
            // Register the Swagger generator, defining one or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "API", Version = "v1" });
//启用auth支持
var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, };
c.AddSecurityRequirement(security);
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{ Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = "header",
Type = "apiKey"
}); });
services.AddAuthentication(options=> {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "Bearer",
ValidAudience = "wr",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(JwtHelper.secretKey)),
RequireSignedTokens = true,
// 将下面两个参数设置为false,可以不验证Issuer和Audience,但是不建议这样做。
ValidateAudience = false,
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
// 是否要求Token的Claims中必须包含 Expires
RequireExpirationTime = true,
// 是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比
ValidateLifetime = true
};
}); services.AddAuthorization(options =>
{
options.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
options.AddPolicy("AdminOrClient", policy => policy.RequireRole("Admin,Client").Build());
});

2. 在Configure方法里,useMVC的前面增加中间件,这样每次Web请求时,会先到 JwtTokenAuth 这里处理验证token

            app.UseMiddleware<JwtTokenAuth>();
app.UseMvc();

3. JwtHelper.cs 里包含颁发和验证token2个方法

        public static string IssueJWT(TokenModelJWT tokenModel)
{
var dateTime = DateTime.UtcNow;
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Jti,tokenModel.Uid.ToString()),//Id
new Claim("Role", tokenModel.Role),//角色
new Claim(JwtRegisteredClaimNames.Iat,dateTime.ToString(),ClaimValueTypes.Integer64)
};
//秘钥
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtHelper.secretKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var jwt = new JwtSecurityToken(
issuer: "Bearer",
claims: claims, //声明集合
expires: dateTime.AddHours(),
signingCredentials: creds); var jwtHandler = new JwtSecurityTokenHandler();
var encodedJwt = jwtHandler.WriteToken(jwt); return encodedJwt;
}
public static TokenModelJWT SerializeJWT(string jwtStr)
{
var jwtHandler = new JwtSecurityTokenHandler();
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
if (jwtToken.ValidTo < DateTime.UtcNow)
return null; object role = new object(); ;
try
{
jwtToken.Payload.TryGetValue("Role", out role);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
var tm = new TokenModelJWT
{
Uid = int.Parse(jwtToken.Id),
Role = role != null ? role.ToString() : "",
};
return tm;
}

4. JwtTokenAuth.cs 中间件验证token,并增加User到httpContext,表示已登录

        public Task Invoke(HttpContext httpContext)
{
//检测是否包含'Authorization'请求头
if (!httpContext.Request.Headers.ContainsKey("Authorization"))
{
return _next(httpContext);
}
var tokenHeader = httpContext.Request.Headers["Authorization"].ToString(); TokenModelJWT tm = JwtHelper.SerializeJWT(tokenHeader);
if (tm != null)
{
//授权
var claimList = new List<Claim>();
var claim = new Claim(ClaimTypes.Role, tm.Role);
claimList.Add(claim);
var identity = new ClaimsIdentity(claimList);
var principal = new ClaimsPrincipal(identity);
httpContext.User = principal;
} return _next(httpContext);
}

把旧系统迁移到.Net Core 2.0 日记 (18) --JWT 认证(Json Web Token)的更多相关文章

  1. 把旧系统迁移到.Net Core 2.0 日记 (15) --Session 改用Redis

    安装Microsoft.Extensions.Caching.Redis.Core NuGet中搜索Microsoft.Extensions.Caching.Redis.Core并安装,此NuGet包 ...

  2. 把旧系统迁移到.Net Core 2.0 日记(1) - Startup.cs 解析

    因为自己到开发电脑转到Mac Air,之前的Webform/MVC应用在Mac 跑不起来,而且.Net Core 2.0 已经比较稳定了. 1. 为什么会有跨平台的.Net Core  近年来,我们已 ...

  3. 把旧系统迁移到.Net Core 2.0 日记 (12) --发布遇到的问题

    1. 开发时是在Mac+MySql, 尝试发布时是在SQL2005+Win 2008 (第一版) 在Startup.cs里,数据库连接要改,分页时netcore默认是用offset关键字分页, 如果用 ...

  4. 把旧系统迁移到.Net Core 2.0 日记 (17) --多租户和SoftDelete

    在EF Core 2.0版本中出现了全局过滤新特性即HasQueryFilter,它出现的意义在哪里?能够解决什么问题呢? 通过HasQueryFilter方法来创建过滤器能够允许我们对访问特定数据库 ...

  5. 把旧系统迁移到.Net Core 2.0 日记(10) -- EF core 和之前版本多对多映射区别

    EF Core 现在不支持多对多映射,只能做2个一对多映射. 比如Product和Category 我现在定义Product和Category是多对多关系. 那么实体定义如下: public clas ...

  6. 把旧系统迁移到.Net Core 2.0 日记(8) - EASYUI datagrid+ Dapper+ 导出Excel

    迁移也没太大变化,有一个, 之前的Request.QueryString 是返回NameValueCollection, 现在则是返回整个字符串. 你要改成Request.Query[“key”] 直 ...

  7. 把旧系统迁移到.Net Core 2.0 日记(5) Razor/HtmlHelper/资源文件

    net core 的layout.cshtml文件有变化, 区分开发环境和非开发环境. 开发环境用的是非压缩的js和css, 正式环境用压缩的js和css <environment includ ...

  8. 把旧系统迁移到.Net Core 2.0 日记(4) - 使用EF+Mysql

    因为Mac 不能装SqlServer, 所以把数据库迁移到MySql,然后EntityFramework要改成Pomelo.EntityFrameworkCore.MySql 数据库迁移时,nvarc ...

  9. 把旧系统迁移到.Net Core 2.0 日记(3) - 详解依赖注入 (转)

    关于DI 依赖注入, 转载这篇文章, 写得很好的. ----------------------------- DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关 ...

随机推荐

  1. Antd-Select组件的深入用法

    一.Antd-Select提供几种类型 最基础版只提供下拉功能的选择器 带搜索功能的下拉选择器 可多选的下拉选择器 可搜索.可多选.可随意输入内容的tag下拉选择器(支持自动分词) 多级联动下拉选择器 ...

  2. PyEngine3D

    git clone https://github.com/ubuntunux/PyEngine3D cd PyEngine3D pip install -r requirements.txt pyth ...

  3. vue中使用vw适配移动端

    推荐看看大漠老师的文章,非常的有收获 如何在Vue项目中使用vw实现移动端适配 1.首先在项目中安装依赖 npm i postcss-aspect-ratio-mini postcss-px-to-v ...

  4. Java离线人脸识别SDK 支持arcface 2.0 最新版

    虹软人脸识别SDK之Java版,支持SDK 1.1+,以及当前最新版本2.0,滴滴,抓紧上车! JDK SDK Win release license status 前言 由于业务需求,最近跟人脸识别 ...

  5. 使用http://start.spring.io/ 生成工程

    今天学习spring-cloud,无意中发现一个spring提供的构建工程的页面,想记录下,发现有个博客写的很好就直接抄过来了.  原文链接: https://blog.csdn.net/u01050 ...

  6. DirectX学习之第一个可运行的工程

    学习一门开发语言的第一件事情当然是搭建一个可运行的环境,然后运行一个可成功执行的案例. 本人在学习DirectX的第一个工程的时候,参考了雨凇MoMo的一篇文章(https://www.xuanyus ...

  7. Unity Shader入门精要之 screen post-processing effect

    本篇记录了学习Unity Shader入门精要的屏幕后处理的一些知识点. OnRenderImage(RenderTexture src, RenderTexture dest) 以上函数是Unity ...

  8. 雷林鹏分享: C# 简介

    C# 简介 C# 是一个现代的.通用的.面向对象的编程语言,它是由微软(Microsoft)开发的,由 Ecma 和 ISO 核准认可的. C# 是由 Anders Hejlsberg 和他的团队在 ...

  9. ROC曲线(receiver-operating-characteristic curve)-阈值评价标准(转)

    转自:http://blog.csdn.net/abcjennifer/article/details/7359370 ROC曲线指受试者工作特征曲线 / 接收器操作特性曲线(receiver ope ...

  10. 常用标签(html+jstl+jsp)

    html:(form.input) (table.tr.td)  div (a. img.span)  h1~h6 (select.option) (br.hr.center)  (link.meta ...