Nancy基于JwtBearer认证的使用与实现
简单使用
第一步 , 用VS创建一个空的ASP.NET Core Web Application
第二步 , 安装相关的NuGet包
通过命令在Package Manager Console执行安装下面的包,也可以用图形界面来完成这一步操作。
Install-Package Microsoft.AspNetCore.Owin -Version 1.1.2 Install-Package Nancy -PreInstall-Package Nancy.Authentication.JwtBearer
其中,Microsoft.AspNetCore.Owin和Nancy是基础包,Nancy.Authentication.JwtBearer是等下要用到的组件包。
第三步 , 修改Startup,添加对Nancy的支持。
public class Startup{ public void Configure(IApplicationBuilder app) { app.UseOwin(x=>x.UseNancy());} }
第四步 , 添加一个Module来验证Nancy是否可以正常使用
public class MainModule : NancyModule{ public MainModule() {Get("/",_=> { return "test";});} }
正常情况下,这个时候运行项目是OK的,大致效果如下:
下面一步就是添加一个Bootstrapper用于启用JwtBearer验证。
public class DemoBootstrapper : DefaultNancyBootstrapper{ protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) { base.ApplicationStartup(container, pipelines); var keyByteArray = Encoding.ASCII.GetBytes("Y2F0Y2hlciUyMHdvbmclMjBsb3ZlJTIwLm5ldA=="); var signingKey = new SymmetricSecurityKey(keyByteArray); var tokenValidationParameters = new TokenValidationParameters{ // The signing key must match!ValidateIssuerSigningKey = true,IssuerSigningKey = signingKey, // Validate the JWT Issuer (iss) claimValidateIssuer = true,ValidIssuer = "http://www.cnblogs.com/catcher1994", // Validate the JWT Audience (aud) claimValidateAudience = true,ValidAudience = "Catcher Wong", // Validate the token expiryValidateLifetime = true,ClockSkew = TimeSpan.Zero}; var configuration = new JwtBearerAuthenticationConfiguration{TokenValidationParameters = tokenValidationParameters}; //enable the JwtBearer authenticationpipelines.EnableJwtBearerAuthentication(configuration);} }
如果使用过Nancy项目自带的其他认证方式(Basic,Forms和Stateless),就会发现下面的才是关键,其他的只是用于JwtBearer认证的配置参数。
pipelines.EnableJwtBearerAuthentication(configuration);
下面简单介绍一下配置参数。
配置参数主要有两个,一个是TokenValidationParameters , 一个是Challenge 。
其中最主要的参数TokenValidationParameters,这是用来验证客户端传过来的token是否合法的!
它位于Microsoft.IdentityModel.Tokens这个命名空间下面。
Challenge参数则是用于指定在Unauthorized时Http响应头中WWW-Authenticate的值。它的默认值是Bearer
注:Challenge参数是从Microsoft.AspNetCore.Authentication.JwtBearer项目借鉴过来的。
到这里, 我们已经完成了对JwtBearer认证的配置和启用,下面还要验证这个配置是否已经生效了!
创建一个新的Module,并在这个Module中使用RequiresAuthentication。
public class SecurityModule : NancyModule{ public SecurityModule() : base("/demo") { //importantthis.RequiresAuthentication();Get("/",_=> { return "JwtBearer authentication";});} }
注: 这里需要引用Nancy.Security这个命名空间
到这里,验证的代码也已经写好了,当我们访问 http://yourdomain.com/demo 的时候
浏览器会提示我们The requested resource requires user authentication , 并且在响应头中我们可以看到WWW-Authenticate对应的值是Bearer。
我们创建一个合法的token值,然后通过Fiddler再发起一次请求,看看能否正常返回我们要的结果。
下面的代码是生成一个测试token用的,其中的JwtSecurityToken对象应当与前面的配置一样,才能确保token是有效的。
private string GetJwt(){ var now = DateTime.UtcNow; var claims = new Claim[]{ new Claim(JwtRegisteredClaimNames.Sub, "demo"), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Iat, now.ToUniversalTime().ToString(), ClaimValueTypes.Integer64)}; //must the same as your setting in your boostrapper classvar symmetricKeyAsBase64 = "Y2F0Y2hlciUyMHdvbmclMjBsb3ZlJTIwLm5ldA=="; var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64); var signingKey = new SymmetricSecurityKey(keyByteArray); var jwt = new JwtSecurityToken(issuer: "http://www.cnblogs.com/catcher1994",audience: "Catcher Wong",claims: claims,notBefore: now,expires: now.Add(TimeSpan.FromMinutes(10)),signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)); var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); var response = new{access_token = encodedJwt,expires_in = (int)TimeSpan.FromMinutes(10).TotalSeconds}; return JsonConvert.SerializeObject(response, new JsonSerializerSettings { Formatting = Formatting.Indented }); }
通过Fiddler执行这个带上了token的请求,大致结果如下 :
可以看到成功取到了相应的内容!
然后是本次测试用的token值相关的信息:
注:用Fiddler发起请求的时候,记得要在请求头部加上Authorization,它的值是Bearer+空格+token值
到这里,已经展示了如何使用这个JwtBearer认证的组件。
下面就介绍一下是怎么实现的这个组件!
如何实现
在继续下面的内容之前,我假设大家对Nancy的Pipelines有所了解,如果不了解的可以参考我以前的下面的链接
Nancy之Pipelines三兄弟(Before After OnError)
Nancy官方的Wike页面。
因为其中的BeforePipeliine和AfterPipeline是实现这个认证组件的重要切入点。
另外,实现上还用了Nancy项目的代码风格去编写的代码,所以你可能会发现与其自带的Basic认证等写法差不多。
从我们上面的例子使用来说明内部实现。
在上面例子的启动器(Bootstrapper)中,我们有一行启用JwtBearer认证的入口。这个入口是IPipelines的一个扩展方法。
/// <summary>/// Module requires JwtBearer authentication/// </summary>/// <param name="pipeline">Bootstrapper to enable</param>/// <param name="configuration">JwtBearer authentication configuration</param>public static void EnableJwtBearerAuthentication(this IPipelines pipeline, JwtBearerAuthenticationConfiguration configuration){JwtBearerAuthentication.Enable(pipeline, configuration); }
在这个扩展方法中,调用了JwtBearerAuthentication这个静态类的Enable方法,同时传递了当前的pipeline和JwtBearer认证的参数给这个方法。
下面是Enable方法的具体实现。
/// <summary>/// Enables JwtBearer authentication for the application/// </summary>/// <param name="pipelines">Pipelines to add handlers to (usually "this")</param>/// <param name="configuration">JwtBearer authentication configuration</param>public static void Enable(IPipelines pipelines, JwtBearerAuthenticationConfiguration configuration){ if (pipelines == null){ throw new ArgumentNullException("pipelines");} if (configuration == null){ throw new ArgumentNullException("configuration");}pipelines.BeforeRequest.AddItemToStartOfPipeline(GetLoadAuthenticationHook(configuration));pipelines.AfterRequest.AddItemToEndOfPipeline(GetAuthenticationPromptHook(configuration)); }
以BeforeRequest为例,我们把一个委托对象加入到了请求之前要处理的一个集合中去。这样在每次请求之前都会去处理这个委托。
所以这里有两个部分。
请求处理之前的token认证
请求处理之后的响应
先来看看请求处理之前的token认证如何处理
private static Func<NancyContext, Response> GetLoadAuthenticationHook(JwtBearerAuthenticationConfiguration configuration) { return context => {Validate(context,configuration); return null;}; }
这里也是一个空壳,用于返回AddItemToStartOfPipeline方法需要的委托对象。
真正处理token的还是Validate这个方法。认证的处理还借助了System.IdentityModel.Tokens.Jwt命名空间下面的JwtSecurityTokenHandler类。
private static void Validate(NancyContext context, JwtBearerAuthenticationConfiguration configuration){ //get the token from request headervar jwtToken = context.Request.Headers["Authorization"].FirstOrDefault() ?? string.Empty; //whether the token value start with Bearerif (jwtToken.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)){jwtToken = jwtToken.Substring("Bearer ".Length);} else{ return;} //verify the tokenif (!string.IsNullOrWhiteSpace(jwtToken)){ try{SecurityToken validatedToken; var tokenHandler = new JwtSecurityTokenHandler(); var validatedClaims = tokenHandler.ValidateToken(jwtToken, configuration.TokenValidationParameters, out validatedToken); //var jwtSecurityToken = validatedToken as JwtSecurityToken;context.CurrentUser = validatedClaims;} catch (Exception){ } } }
要对token进行验证,首先要知道token是从那里来的。常规情况下,都是将这个token放到请求头的Authorization中。
所以第一步是要从请求头中取出Authorization的值。这个值是必须以Bearer开头的一个字符串。注意是Bearer加一个空格!
而我们要验证的部分是去掉开头这部分之后的内容。只需要构造一个JwtSecurityTokenHandler实例并调用这个实例的ValidateToken方法,并把要验证的token值和我们的配置传进去即可。
验证成功后,最为主要的一步是将ValidateToken方法的返回值赋给当前Nancy上下文的CurrentUser!!
当验证失败的时候,ValidateToken方法会抛出一个异常,这里只catch了这个异常,并没有进行其他额外的处理。要处理无非也就是记录日记,可以在这里trace一下,配合Diagnostics的使用。但是目前并没有这样做。
到这里,Before已经OK了,现在要处理After了。
当然对于After,也是只处理401(Unauthorized)的情况。主要是告诉客户端 “当前请求的资源需要用户认证”,并告诉客户端当前请求的资源需要那种认证类型。
private static Action<NancyContext> GetAuthenticationPromptHook(JwtBearerAuthenticationConfiguration configuration){ return context =>{ if (context.Response.StatusCode == HttpStatusCode.Unauthorized){ //add a response header context.Response.WithHeader(JwtBearerDefaults.WWWAuthenticate, configuration.Challenge);}}; }
一个简单的判断加上响应头部的处理。
到这里,这个JwtBearer认证的组件已经ok了。
当然这里只介绍了Pipeline的实现,还有一个是基于NancyModule的实现,本质还是pipeline的处理,所以这里就不累赘了。
转载于:https://blog.51cto.com/12902932/1950337
Nancy基于JwtBearer认证的使用与实现相关推荐
- 认证授权方案之JwtBearer认证
1.前言 回顾:认证方案之初步认识JWT 在现代Web应用程序中,即分为前端与后端两大部分.当前前后端的趋势日益剧增,前端设备(手机.平板.电脑.及其他设备)层出不穷.因此,为了方便满足前端设备与后端 ...
- ASP.NET Core 认证与授权[4]:JwtBearer认证
Bearer认证 HTTP提供了一套标准的身份验证框架:服务器可以用来针对客户端的请求发送质询(challenge),客户端根据质询提供身份验证凭证.质询与应答的工作流程如下:服务器端向客户端返回40 ...
- EMAIL发送系统(C#+基于SMTP认证) 2.0
这个是对于 EMAIL发送系统(C#+基于SMTP认证) 1.0 的改版这个第一版是2002年11月写的,过了一年半了,才有人提意见,就修正了一下,因为后来做的项目一直用不上,也就没有注意到 前段时间 ...
- 基于Forms-Roles认证方式目录权限配置的学习
一直以来网站管理后台的验证代码都是自己在写,这两天学习了一下ASP.NET的基于FORMS认证的方式,只要统一配置就可以,不用每个管理页面都加入验证代码,非常方便实用. 举个例子: 网站结构包括: A ...
- 基于session认证
目前大多数web应用的用户认证机制都是基于session的.用户认证成功后,在服务端生成用户相关的数据保存在session中(当前会话),而发给客户端的sesssion_id 存放到 cookie 中 ...
- 多功能复合机基于用户认证功能的实现过程详解
多功能复合机基于用户认证功能的实现方法 -----网络设备共享案例分析 公司需求:***是一家租售写字楼的服务性企业, ...
- rest_framework11:jwt简单例子/自定制基于jwt认证类
jwt简单例子 一.登陆设置 1.不需要写login的视图类,使用jwt内置的. 2.需要前置条件,已有继承AbstractUser models,并且有数据,用于校验,返回token. urls.p ...
- java token_Java实现基于token认证的方法示例
随着互联网的不断发展,技术的迭代也非常之快.我们的用户认证也从刚开始的用户名密码转变到基于cookie的session认证,然而到了今天,这种认证已经不能满足与我们的业务需求了(分布式,微服务).我们 ...
- svn mysql认证_SVN基于MySQL认证
SVN的简介和工作原理 Subversion(简称svn)是近几年崛起的版本管理软件,是cvs的接班人,目前绝大多数开源软件都使用svn作为代码版本管理软件.Subversion支持linux和win ...
最新文章
- Ubuntu 下安装adobe flash player
- 开发者基础知识游戏,共10关,欢迎挑战
- Redis内核原理及读写一致企业级架构深入剖析1-综合组件环境实战
- PTA5-53 两个有序序列的中位数
- Database2Sharp重要更新之生成Winform框架界面代码
- win11正式版iso镜像如何安装 windows11正式版iso镜像安装方法
- LNK2026	module unsafe for SAFESEH image
- 简单计算器——两种方法
- java安全管理器视频_安全管理器 (Security Manager)
- STM32G030C8T6跑马灯程序V0.2(四)
- PMP培训内容有哪些?都要仔细看!
- Android零基础入门第18节:EditText的属性和使用方法
- Odoo客户成功案例访谈:机加工厂企业信息化的心路历程探讨
- django+vue+nginx+frp搭建漫画网站之接入谷歌统计和百度统计(三)
- 怎样通过穴位按摩来减轻脚踝扭伤的疼痛
- windows server 2012 使用包管理工具choco安装程序
- Centos7.6离线安装显卡驱动
- Android网络开发技术实战详解
- ZYNQ-7的芯片引脚
- 用stitching_detailed拼接图片失败,原因分析(待补充)
热门文章
- php+mysql案例含源码_[源码和文档分享]基于PHP和MYSQL数据库实现的失物招领系统...
- 三轴合并_用两套乐高60107合并成铰接式云梯消防车,看看和60112有什么区别
- jquery audio没有声音_Audio-technica 铁三角 ATH-DSR7BT 头戴式蓝牙无线耳机测评报告 [Soomal]...
- 创建数据账号只有个别表的权限_只有普通权限账号,如何把远程数据库中该用户的数据表导入到本地数据库?...
- 卸载python27_27. 移除元素(Python)
- 为什么爬虫都用python_python为什么叫网络爬虫
- java se 试题_javaSE试题
- java 打包工具_Java打包Windows安装程序
- 史上最全Java集合关系图
- android view 存值,使用ViewModel保存数据