在ASP.NET Web API 2中使用Owin基于Token令牌的身份验证
基于令牌的身份验证
基于令牌的身份验证主要区别于以前常用的常用的基于cookie的身份验证,基于cookie的身份验证在B/S架构中使用比较多,但是在Web Api中因其特殊性,基于cookie的身份验证已经不适合了,因为并不是每一个调用api的客户端都是从浏览器发起,我们面临的客户端可能是手机、平板、或者app。
使用基于Token令牌的身份验证有一些好处:
- 服务器的可伸缩性:发送到服务器的令牌是字包含的,不依赖与共享会话存储
- 松散耦合:前端应用程序位于特定的身份验证机制耦合,令牌是从服务器生成的,并且API构建方式可理解该令牌并进行身份验证
- 适用于移动设备:cookie依赖于浏览器,存储于本机平台,使用token将简化流程
构建后端API
步骤一: 创建Web Api 项目
为了进行代码演示,创建一个相对比较干净的环境,我们新建一个项目演示本次功能,本文使用Visual Studio 2017和 .NTE Framework 4.7。
在Vs中选择新建项目,选择ASP.NET Web 应用程序(.NET Framework) ,命名为OauthExample或者随便你喜欢的名字,然后下一步,选择空模板。ok
步骤二:安装Owin包,并设置“StarUp”类
项目右键,管理Nuget程序包,分别安装
Microsoft.AspNet.WebApi.Owin
Microsoft.Owin.Host.SystemWeb
也可以在程序包管理器输入如下代码安装:
- Install-Package Microsoft.AspNet.WebApi.Owin
- Install-Package Microsoft.Owin.Host.SystemWeb
等待安装完成。
右键项目,移除Global.asax,右键项目,添加OWIN StartUp 类,然后修改代码如下:
- using System.Web.Http;
- using Microsoft.Owin;
- using Owin;
- [assembly: OwinStartup(typeof(OAuthExample.Startup))]
- namespace OAuthExample
- {
- public class Startup
- {
- public void Configuration(IAppBuilder app)
- {
- // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
- HttpConfiguration config = new HttpConfiguration();
- WebApiConfig.Register(config);
- app.UseWebApi(config);
- }
- }
- }
简要说明
- assembly属性设置了启动时要触发的类
- HttpConfiguration对象用于配置API路由等,我们将对象传递给Register方法
- UasWebApi接收对象config,该方法将把Web Api连接到我们的OWIN服务管道
完成后编译一下,检查是否能通过,如果有问题检查一下Nuget包是否安装正确。
步骤三:添加对OAuth承载令牌生成的支持
安装Owin包,Microsoft.Owin.Security.OAuth,再次打开StartUp文件,修改代码如下(斜体):
- using System;
- using System.Web.Http;
- using Microsoft.Owin;
- using Microsoft.Owin.Security.OAuth;
- using Owin;
- [assembly: OwinStartup(typeof(OAuthExample.Startup))]
- namespace OAuthExample
- {
- public class Startup
- {
- public void Configuration(IAppBuilder app)
- {
- // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
- OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
- {
- AllowInsecureHttp = true,
- TokenEndpointPath = new PathString("/oauth/token"),
- AccessTokenExpireTimeSpan = TimeSpan.FromDays(),
- Provider = new CustomAuthorizationServerProvider()
- };
- // Token Generation
- app.UseOAuthAuthorizationServer(OAuthServerOptions);
- app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
- HttpConfiguration config = new HttpConfiguration();
- WebApiConfig.Register(config);
- app.UseWebApi(config);
- }
- }
- }
在这里,我们从类“OAuthAuthorizationServerOptions”创建了新实例,并设置选项如下:
- 允许客户端使用http协议请求
- 令牌生成路径为"/oauth/token" ,即通过路径host: port:/oauth/token 获取令牌信息
- 设置令牌的有效时间为一天,如果用户在令牌发出24小时候使用令牌进行身份验证,请求将被拒绝,并返回状态码
- 我们在名为“CustomAuthorizationServerProvider”的类中实现了如何用户票据的验证和发放
最后我们将此选项传递给扩展方法“ UseOAuthAuthorizationServer”,以便将身份验证中间件添加到管道中。
步骤四:实现“CustomAuthorizationServerProvider”类
在项目中添加名为“ Providers”的新文件夹,然后添加名为“ SimpleAuthorizationServerProvider”的新类,在下面粘贴代码片段:
- using System.Security.Claims;
- using System.Threading.Tasks;
- using Microsoft.Owin.Security.OAuth;
- namespace OAuthExample.Providers
- {
- public class CustomAuthorizationServerProvider : OAuthAuthorizationServerProvider
- {
- /// <summary>
- /// Called to validate that the origin of the request is a registered "client_id", and that the correct credentials for that client are
- /// present on the request. If the web application accepts Basic authentication credentials,
- /// context.TryGetBasicCredentials(out clientId, out clientSecret) may be called to acquire those values if present in the request header. If the web
- /// application accepts "client_id" and "client_secret" as form encoded POST parameters,
- /// context.TryGetFormCredentials(out clientId, out clientSecret) may be called to acquire those values if present in the request body.
- /// If context.Validated is not called the request will not proceed further.
- /// </summary>
- /// <param name="context">The context of the event carries information in and results out.</param>
- public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
- {
- context.Validated();
- }
- /// <summary>
- /// Called when a request to the Token endpoint arrives with a "grant_type" of "password". This occurs when the user has provided name and password
- /// credentials directly into the client application's user interface, and the client application is using those to acquire an "access_token" and
- /// optional "refresh_token". If the web application supports the
- /// resource owner credentials grant type it must validate the context.Username and context.Password as appropriate. To issue an
- /// access token the context.Validated must be called with a new ticket containing the claims about the resource owner which should be associated
- /// with the access token. The application should take appropriate measures to ensure that the endpoint isn’t abused by malicious callers.
- /// The default behavior is to reject this grant type.
- /// See also http://tools.ietf.org/html/rfc6749#section-4.3.2
- /// </summary>
- /// <param name="context">The context of the event carries information in and results out.</param>
- public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
- {
- context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
- //这里是验证用户名和密码,可以根据项目情况自己实现
- if (!(context.UserName == "zhangsan" && context.Password == ""))
- {
- context.SetError("invalid_grant", "The user name or password is incorrect.");
- return;
- }
- //可以随便添加
- var identity = new ClaimsIdentity(context.Options.AuthenticationType);
- identity.AddClaim(new Claim("sub", context.UserName));
- identity.AddClaim(new Claim("role", "user"));
- context.Validated(identity);
- }
- }
- }
步骤五:允许ASP.NET Web Api跨域请求
使用nuget安装程序包,Install-Package Microsoft.Owin.Cors
然后在Startup类中添加如下代码,最终代码如下:
- using System;
- using System.Web.Http;
- using Microsoft.Owin;
- using Microsoft.Owin.Security.OAuth;
- using OAuthExample.Providers;
- using Owin;
- [assembly: OwinStartup(typeof(OAuthExample.Startup))]
- namespace OAuthExample
- {
- public class Startup
- {
- public void Configuration(IAppBuilder app)
- {
- // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
- OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
- {
- AllowInsecureHttp = true,
- TokenEndpointPath = new PathString("/token"),
- AccessTokenExpireTimeSpan = TimeSpan.FromDays(),
- Provider = new CustomAuthorizationServerProvider()
- };
- // Token Generation
- app.UseOAuthAuthorizationServer(OAuthServerOptions);
- app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
- HttpConfiguration config = new HttpConfiguration();
- WebApiConfig.Register(config);
- app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
- app.UseWebApi(config);
- }
- }
- }
代码测试
我们添加一个测试空的Order控制,用来测试一下上面的实现:
- [RoutePrefix("api/Orders")]
- public class OrdersController : ApiController
- {
- [Authorize]
- [Route("")]
- public IHttpActionResult Get()
- {
- return Ok(Order.CreateOrders());
- }
- }
- #region Helpers
- public class Order
- {
- public int OrderID { get; set; }
- public string CustomerName { get; set; }
- public string ShipperCity { get; set; }
- public Boolean IsShipped { get; set; }
- public static List<Order> CreateOrders()
- {
- List<Order> OrderList = new List<Order>
- {
- new Order {OrderID = , CustomerName = "Taiseer Joudeh", ShipperCity = "Amman", IsShipped = true },
- new Order {OrderID = , CustomerName = "Ahmad Hasan", ShipperCity = "Dubai", IsShipped = false},
- new Order {OrderID = ,CustomerName = "Tamer Yaser", ShipperCity = "Jeddah", IsShipped = false },
- new Order {OrderID = ,CustomerName = "Lina Majed", ShipperCity = "Abu Dhabi", IsShipped = false},
- new Order {OrderID = ,CustomerName = "Yasmeen Rami", ShipperCity = "Kuwait", IsShipped = true}
- };
- return OrderList;
- }
- }
- #endregion
下面使用PostMan进行模拟测试.
在未授权时,直接访问 http://localhost:56638/api/orders得到如下结果:
模拟授权访问,先获取令牌:
将令牌附加到Order请求,再次尝试访问:
可以看到已经能正常获取到数据,打开调试,看一下方法中的变量如下:
总结
一直觉得WebApi和MVC很多都一样的东西,在实际应用中还是有不少区别,关于OAuth、JWT等等在WebApi中使用较多,本文是参照文末连接做的一个总结,细看下原po的时间都已经是14年的文章了。马上要aspnet core 3.2都要发布了,现在却还在补以前的知识,惭愧的很!
参考链接:
Token Based Authentication using ASP.NET Web API 2, Owin, and Identity
Enable OAuth Refresh Tokens in AngularJS App using ASP .NET Web API 2, and Owin
在ASP.NET Web API 2中使用Owin基于Token令牌的身份验证的更多相关文章
- 在ASP.NET Web API 2中使用Owin OAuth 刷新令牌(示例代码)
在上篇文章介绍了Web Api中使用令牌进行授权的后端实现方法,基于WebApi2和OWIN OAuth实现了获取access token,使用token访问需授权的资源信息.本文将介绍在Web Ap ...
- ASP.NET Web API 2 中的属性路由使用(转载)
转载地址:ASP.NET Web API 2 中的属性路由使用
- 在ASP.NET Web API项目中使用Hangfire实现后台任务处理
当前项目中有这样一个需求:由前端用户的一个操作,需要触发到不同设备的消息推送.由于推送这个具体功能,我们采用了第三方的服务.而这个服务调用有时候可能会有延时,为此,我们希望将消息推送与用户前端操作实现 ...
- ASP.NET Web API 2 中的特性路由
ASP.NET MVC 5.1 开始已经支持基于特性的路由(http://attributerouting.net),ASP.NET WEB API 2 同时也支持了这一特性. 启用特性路 由只需要在 ...
- ASP.NET Web API 2中的错误处理
前几天在webapi项目中遇到一个问题:Controller构造函数中抛出异常时全局过滤器捕获不到,于是网搜一把写下这篇博客作为总结. HttpResponseException 通常在WebAPI的 ...
- [翻译]ASP.NET Web API 2 中的全局错误处理
目录 已存在的选项 解决方案预览 设计原则 什么时候去用 方案详情 示例 附录: 基类详情 原文链接 Global Error Handling in ASP.NET Web API 2 由于翻译水平 ...
- (转)【ASP.NET Web API】Authentication with OWIN
概述 本文说明了如何使用 OWIN 来实现 ASP.NET Web API 的验证功能,以及在客户端与服务器的交互过程中,避免重复提交用户名和密码的机制. 客户端可以分为两类: JavaScript: ...
- ASP.NET Web API实现微信公众平台开发(一)服务器验证
最近朋友的微信公众号准备做活动,靠固定的微信公众平台模版搞定不了,于是请我代为开发微信后台.鉴于我也是第一次尝试开发微信后台,所以也踩了不少坑,此系列博客将会描述微信公众号各项功能的实现. 先决条件 ...
- integration asp.net web api with autofac and owin
There is an example project showing Web API in conjunction with OWIN self hosting https://github.com ...
随机推荐
- 数据挖掘--OPTICS
OPTICS是基于DBSCAN算法的缺陷提出来的一个算法. 核心思想:为每个数据对象计算出一个顺序值(ordering).这些值代表了数据对象的基于密度的族结构,位于同一个族的数据对象具有相近的顺序值 ...
- hydra使用,实例介绍
hydra 是一个网络帐号破解工具,支持多种协议.其作者是van Hauser,David Maciejak与其共同维护.hydra在所有支持GCC的平台能很好的编译,包括Linux,所有版本的BSD ...
- web-程序逻辑问题
题目 查看源码 http://ctf5.shiyanbar.com/web/5/index.txt 代码如下 <html> <head> welcome to simplexu ...
- django学习-视图练习
写一个真正有用的视图 每个视图必须要做的只有两件事: 返回一个包含被请求页面内容的HttpResponse对象,或抛出一个异常,比如Http404. 至于你还想干些什么,随便你. 你的视图可以从数据库 ...
- zz 机器学习系统或者SysML&DL笔记
机器学习系统或者SysML&DL笔记(一) Oldpan 2019年5月12日 0条评论 971次阅读 1人点赞 在使用过TVM.TensorRT等优秀的机器学习编译优化系统以及Py ...
- 论文阅读笔记六十三:DeNet: Scalable Real-time Object Detection with Directed Sparse Sampling(CVPR2017)
论文原址:https://arxiv.org/abs/1703.10295 github:https://github.com/lachlants/denet 摘要 本文重新定义了目标检测,将其定义为 ...
- Linux性能优化实战学习笔记:第八讲
一.环境准备 1.在第6节的基础上安装dstat wget http://mirror.centos.org/centos/7/os/x86_64/Packages/dstat-0.7.2-12.el ...
- [LeetCode] 598. Range Addition II 范围相加之二
Given an m * n matrix M initialized with all 0's and several update operations. Operations are repre ...
- 阅读java编程思想之一切都是对象
温故而知新--- 1. 用句柄操作对象 现实生活中,我们可以把遥控器当作句柄,电视机当作对象.当我们拿到句柄(遥控器)的时候,我们是可以控制对象的(电视机).比如说调节音量大小,色彩等.那么在程序里, ...
- 第四次实验报告:使用Packet Tracer理解RIP路由协议
目录 1 实验目的 2 实验内容 3. 实验报告 3.1 建立网络拓扑结构 3.2 配置参数 3.3 测试网络连通性 3.4 理解RIP路由表建立和更新 4. 理解RIP消息传得慢 5. 拓展 1 实 ...