ASP.NET Core Token认证
2016-07-14 17:47
555 查看
翻译:Token Authentication in ASP.NET Core
令牌认证(Token Authentication)已经成为单页应用(SPA)和移动应用事实上的标准。即使是传统的B/S应用也能利用其优点。优点很明白:极少的服务端数据管理、可扩展性、可以使用单独的认证服务器和应用服务器分离。如果你对令牌(token)不是太了解,可以看这篇文章( overview of token authentication and JWTs)
令牌认证在asp.net core中集成。其中包括保护Bearer Jwt的路由功能,但是移除了生成token和验证token的部分,这些可以自定义或者使用第三方库来实现,得益于此,MVC和Web api项目可以使用令牌认证,而且很简单。下面将一步一步实现,代码可以在( 源码)下载。
ASP.NET Core令牌验证
首先,背景知识:认证令牌,例如JWTs,是通过http 认证头传递的,例如:GET /foo Authorization: Bearer [token]
令牌可以通过浏览器cookies。传递方式是header或者cookies取决于应用和实际情况,对于移动app,使用headers,对于web,推荐在html5 storage中使用cookies,来防止xss攻击。
asp.net core对jwts令牌的验证很简单,特别是你通过header传递。
1、生成 SecurityKey,这个例子,我生成对称密钥验证jwts通过HMAC-SHA256加密方式,在startup.cs中:
// secretKey contains a secret passphrase only your server knows var secretKey = "mysupersecret_secretkey!123"; var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
验证 header中传递的JWTs
在Startup.cs中,使用Microsoft.AspNetCore.Authentication.JwtBearer中的
UseJwtBearerAuthentication方法获取受保护的api或者mvc路由有效的jwt。
var tokenValidationParameters = new TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = "ExampleIssuer", // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = "ExampleAudience", // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here: ClockSkew = TimeSpan.Zero }; app.UseJwtBearerAuthentication(new JwtBearerOptions { AutomaticAuthenticate = true, AutomaticChallenge = true, TokenValidationParameters = tokenValidationParameters });
通过这个中间件,任何[Authorize]的请求都需要有效的jwt:
签名有效;
过期时间;
有效时间;
Issuer 声明等于“ExampleIssuer”
订阅者声明等于 “ExampleAudience”
如果不是合法的JWT,请求终止,issuer声明和订阅者声明不是必须的,它们用来标识应用和客户端。
在cookies中验证JWTs
ASP.NET Core中的cookies 认证不支持传递jwt。需要自定义实现 ISecureDataFormat接口的类。现在,你只是验证token,不是生成它们,只需要实现Unprotect方法,其他的交给System.IdentityModel.Tokens.Jwt.
JwtSecurityTokenHandler这个类处理。
using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http.Authentication; using Microsoft.IdentityModel.Tokens; namespace SimpleTokenProvider { public class CustomJwtDataFormat : ISecureDataFormat<AuthenticationTicket> { private readonly string algorithm; private readonly TokenValidationParameters validationParameters; public CustomJwtDataFormat(string algorithm, TokenValidationParameters validationParameters) { this.algorithm = algorithm; this.validationParameters = validationParameters; } public AuthenticationTicket Unprotect(string protectedText) => Unprotect(protectedText, null); public AuthenticationTicket Unprotect(string protectedText, string purpose) { var handler = new JwtSecurityTokenHandler(); ClaimsPrincipal principal = null; SecurityToken validToken = null; try { principal = handler.ValidateToken(protectedText, this.validationParameters, out validToken); var validJwt = validToken as JwtSecurityToken; if (validJwt == null) { throw new ArgumentException("Invalid JWT"); } if (!validJwt.Header.Alg.Equals(algorithm, StringComparison.Ordinal)) { throw new ArgumentException($"Algorithm must be '{algorithm}'"); } // Additional custom validation of JWT claims here (if any) } catch (SecurityTokenValidationException) { return null; } catch (ArgumentException) { return null; } // Validation passed. Return a valid AuthenticationTicket: return new AuthenticationTicket(principal, new AuthenticationProperties(), "Cookie"); } // This ISecureDataFormat implementation is decode-only public string Protect(AuthenticationTicket data) { throw new NotImplementedException(); } public string Protect(AuthenticationTicket data, string purpose) { throw new NotImplementedException(); } } }
在startup.cs中调用
var tokenValidationParameters = new TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = "ExampleIssuer", // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = "ExampleAudience", // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here: ClockSkew = TimeSpan.Zero }; app.UseCookieAuthentication(new CookieAuthenticationOptions { AutomaticAuthenticate = true, AutomaticChallenge = true, AuthenticationScheme = "Cookie", CookieName = "access_token", TicketDataFormat = new CustomJwtDataFormat( SecurityAlgorithms.HmacSha256, tokenValidationParameters) });
如果请求中包含名为access_token的cookie验证为合法的JWT,这个请求就能返回正确的结果,如果需要,你可以加上额外的jwt chaims,或者复制jwt chaims到ClaimsPrincipal在
CustomJwtDataFormat.Unprotect方法中,上面是验证token,下面将在asp.net core中生成token。
ASP.NET Core生成Tokens
在asp.net 4.5中,这个UseOAuthAuthorizationServer中间件可以轻松的生成tokens,但是在asp.net core取消了,下面写一个简单的token生成中间件,最后,有几个现成解决方案的链接,供你选择。简单的token生成节点
首先,生成 POCO保存中间件的选项. 生成类:
TokenProviderOptions.cs
200 OK Content-Type: application/json { "access_token": "eyJhb...", "expires_in": 300 }
View Code
你可以使用jwt工具查看生成的jwt内容。如果开发的是移动应用或者单页应用,你可以在后续请求的header中存储jwt,如果你需要在cookies中存储的话,你需要对代码修改一下,需要将返回的jwt字符串添加到cookie中。
测试下:
其他方案
下面是比较成熟的项目,可以在实际项目中使用:AspNet.Security.OpenIdConnect.Server – ASP.NET 4.x的验证中间件。
OpenIddict – 在identity上添加OpenId验证。
IdentityServer4 – .NET Core认证中间件(现在测试版本)。
下面的文章可以让你更加的了解认证:
Overview of Token Authentication Features
How Token Authentication Works in Stormpath
Use JWTs the Right Way!
谢谢阅读,第一次翻译。。。。。。。。
请多多指正。。。
相关文章推荐
- asp.net mvc 之旅 —— 第六站 ActionFilter的应用及源码分析
- ASP.NET Web API 自定义MediaType实现jsonp跨域调用
- Asp.Net Unix时间戳和DateTime类型转换
- 转:ASP.NET 使用Ajax
- ASP.NET MD5加密
- 收藏:ASP.NET提供文件下载函数(支持大文件、续传、速度限制、资源占用小) (转自: Arhrun)
- 各版本IIS下ASP.net请求处理过程区别
- ASP.net:截取固定长度字符串显示在页面,多余部分显示为省略号
- ASP.NET发送电子邮件
- asp.net SessionState之sqlserver模式
- asp.net 如何引用dll
- [译]初识.NET Core & ASP.NET Core
- 【Asp.Net Core】一、Visual Studio 2015 和 .NET Core 安装
- 为何没有.aspx.designer.cs文件?
- 【转】asp.net(c#)加密解密算法之sha1、md5、des、aes实现源码详解
- ASP.NET Web API系列——选择Web API还是WCF
- 在 ASP.NET MVC 项目中使用 WebForm
- asp.net webapi 自托管插件式服务
- 关于.NET、ASP.NET、C#、WinFrom、MVC以及WebForm的简单描述
- ASP.NET里面,如果设置了form的 onsubmit="return false;"之后,就不能提交按钮了?