ASP.NET核心令牌认证详解
令牌认证已经成为单页应用和移动应用的事实标准。即使是传统的B/S应用程序也可以利用它的优势。优势显而易见:很少的服务器数据管理、可扩展性以及使用独立的身份验证服务器和应用程序服务器。
如果您不太了解令牌,可以阅读本文(令牌认证和JWTS概述)
令牌认证集成在ASP.NET核心网中。它包括了保护承载Jwt的路由功能,但去掉了生成令牌和验证令牌的部分,可以通过使用第三方库进行定制或实现。得益于此,MVC和Web api项目可以使用令牌认证,而且非常简单。下面将逐步实现,代码可以从(源代码)下载。
ASP。NET核心令牌验证
首先,背景知识:身份验证令牌(如JWTs)通过http身份验证头传递,例如:
Get/fooauthorization :承载【token】token可以通过浏览器进行cookies。根据应用和实际情况,交付模式是header或cookies。对于移动应用程序,使用标题,对于网络,建议在html5存储中使用cookies来防止xss攻击。
ASP.NET核对jwts令牌的验证非常简单,尤其是当你通过header传递的时候。
1.生成安全性密钥。在这个例子中,我生成对称密钥来验证jwts是由HMAC-SHA256加密的。在startup.cs中:
//secretKey包含一个秘密密码只有您的服务器知道secretKey=' mysuperservice _ secretKey!123';var signingKey=新的SymmetricSecurityKey(编码。ASCII . GetBytes(secretKey));验证头中传递的JWTs
在Startup.cs中,使用微软的UseJwtBearerAuthentication方法。获取受保护api或mvc路由的有效jwts。
var token validation parameters=new token validation parameters {//签名密钥必须匹配!ValidateIssuerSigningKey=true,IssuerSigningKey=signingKey,//验证JWT发行者(iss)声明ValidateIssuer=true,ValidIssuer=' ExampleIssuer ',//验证JWT受众(aud)声明validateaccount=true,validateaccount=' exampleaccount ',//验证令牌到期ValidateLifetime=true,//如果希望允许一定量的时钟漂移,请在此设置: ClockSkew=TimeSpan。零};app。UseJwtBearerAuthentication(新的JwtBearerOptions { AutomaticAuthenticate=true,AutomaticChallenge=true,TokenValidationParameters=TokenValidationParameters });使用这个中间件,任何对[授权]的请求都需要一个有效的jwt:
签名有效;
到期时间;
有效时间;
发行者声明等于“范例发行者”
订阅者声明等于“示例受众”
如果它不是合法的JWT,则请求被终止,并且发行者声明和订户声明不是必需的,它们用于识别应用程序和客户端。
在cookies中验证JWTs
ASP.NET核心中的Cookies认证不支持通过jwt。需要定制实现ISecureDataFormat接口的类。现在,您只需要实现Unprotect方法,而不是生成token,剩下的就交给类系统了。identity model . token . jwt . jwtsecuritytokenhandler。
使用系统;使用系统IdentityModel .代币。Jwt使用系统。安全。索赔;使用微软。身份验证;使用微软AspNetCore。Http。认证;使用微软。标识模型。令牌;命名空间SimpleTokenProvider { public class customjwtdata format : isecuredata format authenticationticket { private readonly string算法;私有只读令牌验证参数验证参数;public CustomJwtDataFormat(字符串算法,令牌验证参数验证参数){ this。算法=算法;这个。验证参数=验证参数;} public AuthenticationTicket Unprotect(字符串受保护文本)=Unprotect(受保护文本,null);public AuthenticationTicket Unprotect(字符串保护文本,字符串用途){ var handler=new JwtSecurityTokenHandler();ClaimsPrincipal主体=nullSecurityToken validToken=null尝试{ principal=handler .ValidateToken(protectedText,this.validationParameters,out validate token);var validJwt=validToken as JwtSecurityToken;if(validJwt==null){ 0抛出新的ArgumentException(“”无效的JWT ');} if(!validJwt .标题。代数等于(算法,字符串比较.序数)){抛出新的参数异常($ '算法必须是{算法} ');} //此处JWT声明的附加自定义验证(如果有)} catch(SecurityTokenValidationException){ 0返回null } catch(ArgumentException){ 0返回null} //验证通过。返回有效的AuthenticationTicket:返回新的AuthenticationTicket(主体,新的AuthenticationProperties(),' Cookie ');} //此ISecureDataFormat实现是只解码的公共字符串保护(身份验证选择集数据){ 0抛出新的notimplementdexception();}公共字符串保护(身份验证选择集数据,字符串用途){抛出新的notimplementdexception();} }}在startup.cs中调用
var令牌验证参数=新令牌验证参数{//签名密钥必须匹配!ValidateIssuerSigningKey=true,IssuerSigningKey=signingKey,//验证JWT发行者(国际空间站)声明ValidIssuer发卡行=true,ValidIssuer发卡行='example发卡行',//验证JWT受众(澳元)声明validateaccount=true,validate account=' example account ',//验证令牌到期ValidateLifetime=true,//如果希望允许一定量的时钟漂移,请在此设置:时钟时钟=时间跨度.零};应用程序.UseCookieAuthentication(新的CookieAuthenticationOptions { AutomaticAuthenticate=true,AutomaticChallenge=true,AuthenticationScheme='Cookie ',CookieName='access_token ',票证数据格式=新的customjwtdata格式(安全算法.HmacSha256,token validation parameters)});如果请求中包含名为访问令牌的甜饼干验证为合法的JWT,这个请求就能返回正确的结果,如果需要,你可以加上额外的jwt chaims,或者复制jwt chaims到ClaimsPrincipal在CustomJwtDataFormat .撤消保护方法中,上面是验证令牌,下面将在ASP。网核心中生成令牌。
ASP .净核心生成代币
在ASP。NET 4.5中,这个UseOAuthAuthorizationServer中间件可以轻松的生成代币,但是在ASP。网核心取消了,下面写一个简单的代币生成中间件,最后,有几个现成解决方案的链接,供你选择。
简单的代币生成节点
首先,生成少保存中间件的选项。生成类:令牌提供程序。铯
使用系统;使用微软。标识模型。令牌;命名空间SimpleTokenProvider { public class token provideroptions { public string Path { get;设置;}='/token ';公共字符串发行者{获取设置;}公共字符串观众{获取设置;}公共时间跨度到期{获取设置;}=时间跨度.从分钟(5);public SigningCredentials SigningCredentials { get;设置;} }}现在自己添加一个中间件,asp.net核心的中间件类一般是这样的:
使用系统IdentityModel .代币。Jwt使用系统。安全。索赔;使用系统。线程化。任务;使用微软AspNetCore。超文本传送协议(Hyper Text Transport Protocol的缩写)使用微软。扩展。选项;使用牛顿英尺.Json命名空间SimpleTokenProvider { public class令牌提供程序rmidle ware { private readonly request delegate _ next;私有只读令牌提供程序选项;公共令牌提供者中间件(请求委托next,ioptonstkenprovideroptions选项){ _ next=next_选项=选项.价值;}公共任务调用(HttpContext上下文){ //如果请求路径不匹配,跳过If(!语境请求。路径。等于(_选项。路径,字符串比较。序数)){ return _next(上下文);} //请求必须是带有内容类型:应用程序/x-www-form-urlencoded的POST if(!语境请求。方法。等于(' POST ')| |!语境请求。HasFormContentType){ context .回应。状态代码=400返回上下文。响应。写异步(错误的请求));}返回GenerateToken(上下文);} }}这个中间件类接受令牌提供程序作为参数,当有请求且请求路径是设置的路径(令牌或者API/令牌),调用方法执行,令牌节点只对邮政请求而且包括表单-urlencoded内容类型(内容类型:应用程序/x-www-form-urlencoded),因此调用之前需要检查下内容类型。
最重要的是GenerateToken,这个方法需要验证用户的身份,生成jwt,传回jwt:
私有异步任务生成器(HttpContext上下文){ var username=context .请求。表单['用户名'];var密码=上下文。请求。表单['密码'];var identity=await GetIdentity(用户名、密码);if (identity==null) { context .回应。状态代码=400等待上下文。响应。写异步(用户名或密码无效));返回;} var now=DateTime .UtcNow//具体添加jti(随机随机数)、iat(发布时间戳)和sub(主题/用户)声明。//如果您想要: var索赔=新索赔[]{新索赔(JwtRegisteredClaimNames)、可以在此添加其他索赔Sub,用户名),新索赔(JwtRegisteredClaimNames .Jti,Guid .NewGuid().ToString()),新索赔Iat,ToUnixEpochDate(现在)。ToString(),ClaimValueTypes .整数64)};//创建JWT并将其写入字符串var jwt=new JwtSecurityToken(发行人: _ options .发行人,audience: _options .观众,索赔:索赔,不是以前现在:现在到期:添加(_选项。到期),签名凭据: _选项.签署证书);var encoderwt=new JwtSecurityTokenHandler().写令牌(jwt);var response=new { access _ token=encoderwt,expires_in=(int)_options .过期时间总秒数};//序列化并返回响应上下文。响应。content type=' application/JSON ';等待上下文。响应WriteAsync(JsonConvert .SerializeObject(响应,新JsonSerializerSettings {格式化=格式化.缩进}));}大部分代码都很官方,JwtSecurityToken类生成jwt,JwtSecurityTokenHandler将jwt编码,你可以在要求中添加任何查姆斯。验证用户身份只是简单的验证,实际情况肯定不是这样的,你可以集成身份框架或者其他的,对于这个实例只是简单的硬编码:
private taskcaleimsidentity GetIdentity(字符串用户名,字符串密码){ //显然不要在生产中这样做!如果(用户名=='TEST '密码==' TEST 123 '){ 0返回任务.从结果(新索赔)实体(新系统安全。校长。泛型(用户名、“Token”)、新的Claim[]{ });} //凭据无效,或者帐户不存在返回任务from resultclaimsidentity(null);}添加一个将日期时间生成时间戳的方法:
公共静态长ToUnixEpochDate(日期时间日期)=(长)数学.回合((日期tonversaltime()-新的日期时间偏移量(1970,1,1,0,0,0,时间跨度.零)。总秒数);现在,你可以将这个中间件添加到startup.cs中了:
使用系统。文字;使用微软AspNetCore。建设者使用微软。托管;使用微软。扩展。配置;使用微软。扩展。依赖注射;使用微软。扩展。日志记录;使用微软。扩展。选项;使用微软。标识模型。令牌;命名空间SimpleTokenProvider{ public分部类启动{公共启动(ihostingenvironmentenv){ var builder=新配置生成器().AddJsonFile('appsettings.json ',可选: true);配置=构建器build();} public IConfigurationroot Configuration { get;设置;} public void ConfigureServices(IServiceCollection services){ services .AddMvc();} //每个令牌都将使用的密钥。//在生产中,您应该将它安全地存储在环境变量//或密钥管理工具中。不要将此硬编码到您的应用程序中!私有静态只读字符串secretKey='我的超级secretKey _ secretKey!123';公共空配置(IApplicationBuilder应用程序,IHostingEnvironment env,ILoggerFactory记录器工厂){记录器工厂.添加控制台(日志级别。调试);伐木工厂AddDebug();应用程序.UseStaticFiles();//添加JWT生成端点: var signing key=new symmetricccsecuritykey(编码. ASCII。GetBytes(secretKey));var options=新令牌提供程序{ account='示例帐户',发卡行='example发卡行',签名凭据=新的签名凭据(签名密钥,安全性算法.HmacSha256),};应用程序.使用中间件令牌提供程序中间件(选项。创建(选项));应用程序.UseMvc();} }}测试一下,推荐使用铬的邮递员:
发布/令牌内容-类型:应用程序/x-www-form-URL encoded username=TESTpassword=test 123结果:好的
内容类型:应用程序/JSON { ' access _ token ' : ' EyJHb . ',' expires_in': 300}
你可以使用jwt工具查看生成的jwt内容。如果开发的是移动应用或者单页应用,你可以在后续请求的页眉中存储jwt,如果你需要在饼干中存储的话,你需要对代码修改一下,需要将返回的jwt字符串添加到甜饼干中。测试下:
其他方案
下面是比较成熟的项目,可以在实际项目中使用:
AspNet .安全性。开放连接。服务器ASP。NET 4。x的验证中间件OpenIddict在身份上添加OpenId验证识别服务器4。净核心认证中间件(现在测试版本)。下面的文章可以让你更加的了解认证:
令牌身份验证功能概述令牌身份验证如何在风暴路径中工作正确使用JWTs!以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
版权声明:ASP.NET核心令牌认证详解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。