基于令牌的身份验证

基于令牌的身份验证主要区别于以前常用的基于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包,并设置“StartUp”类

项目右键,管理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=316888HttpConfiguration 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=316888OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions(){AllowInsecureHttp = true,TokenEndpointPath = new PathString("/oauth/token"),AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),Provider = new CustomAuthorizationServerProvider()};// Token Generationapp.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小时候使用令牌进行身份验证,请求将被拒绝,并返回401状态码
  • 我们在名为“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 == "123456")){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=316888OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions(){AllowInsecureHttp = true,TokenEndpointPath = new PathString("/token"),AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),Provider = new CustomAuthorizationServerProvider()};// Token Generationapp.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 Helperspublic 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 = 10248, CustomerName = "Taiseer Joudeh", ShipperCity = "Amman", IsShipped = true },new Order {OrderID = 10249, CustomerName = "Ahmad Hasan", ShipperCity = "Dubai", IsShipped = false},new Order {OrderID = 10250,CustomerName = "Tamer Yaser", ShipperCity = "Jeddah", IsShipped = false },new Order {OrderID = 10251,CustomerName = "Lina Majed", ShipperCity = "Abu Dhabi", IsShipped = false},new Order {OrderID = 10252,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令牌的身份验证相关推荐

  1. ASP.NET Web API 2 中的属性路由使用(转载)

    转载地址:ASP.NET Web API 2 中的属性路由使用 转载于:https://www.cnblogs.com/yxlblogs/p/3638625.html

  2. ASP.NET Web API WebHost宿主环境中管道、路由

    ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境 ...

  3. ASP.NET Web API中的Controller

    虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...

  4. 监控系统简介(二):使用 App Metrics 在 ASP.NET Web API 中记录指标

    回顾 在<监控系统简介:使用 Prometheus 与 Grafana>一文中,我们了解了什么是监控系统,Prometheus 这一监控工具及它提供的数据类型.PromQL 以及 Graf ...

  5. ASP.NET Web API Model-ModelBinder

    ASP.NET Web API Model-ModelBinder 前言 本篇中会为大家介绍在ASP.NET Web API中ModelBinder的绑定原理以及涉及到的一些对象模型,还有简单的Mod ...

  6. ASP.NET Web API 安全筛选器

    原文:https://msdn.microsoft.com/zh-cn/magazine/dn781361.aspx 身份验证和授权是应用程序安全的基础.身份验证通过验证提供的凭据来确定用户身份,而授 ...

  7. ASP.NET Web API 2 过滤器

    Ø  前言 我们知道 ASP.NET Web API 过滤器,也是属于消息处理机制中的一部分.正因如此,我们经常使用它来完成对请求的授权验证.参数验证,以及请求的 Log 记录,程序异常捕获等. 1. ...

  8. ASP.NET Web API 记录请求响应数据到日志的一个方法

    原文:ASP.NET Web API 记录请求响应数据到日志的一个方法 原文:http://blog.bossma.cn/dotnet/asp-net-web-api-log-request-resp ...

  9. ASP.NET Web API 控制器创建过程

    前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病去如抽丝.这两天状态才好了一点,让我理解了什么才是革命 ...

最新文章

  1. 【整理】如何翻译SAP事务代码描述
  2. 数据结构基础(1) --Swap Bubble-Sort Select-Sort
  3. Corba传值包含中文解决
  4. Spring各模块的功能及互相之间的关系
  5. android studio中tabhost自定义,Android Studio——TabWiget组件实现(带图标签)
  6. ekho嵌入式Linux移植全过程
  7. 基于自适应惯性权重的樽海鞘群算法
  8. 美通社企业新闻汇总 | 2019.1.21 | 春节访日可享受更多免税优惠;勃林格殷格翰国产化猪疫苗上市...
  9. 情感脑机接口与跨被试情感模型问题研究
  10. 神马笔记 版本1.8.0——删除笔记/文件夹·技术细节篇
  11. matlab神经网络工具箱实现两个输入的BP神经网络
  12. 第十一天 乐在其中-Android与远端之JDBC
  13. 青藤云Webshell查杀绕过
  14. element日历上月下月样式修改
  15. 加药装置 全自动加药装置 示踪加药装置介绍
  16. 计算机专业树立职业理想,对理想职业的要求
  17. 极客应如何创业?(一)
  18. 淘宝/天猫获得淘宝商品详情 API 万邦接口返回值说明
  19. 12306 中铁银通卡积分,积分受让人
  20. HTML标签大全(很全哦).

热门文章

  1. 对比Oracle和Mysql在锁机制上的类似和差异点
  2. MySql DDL语言(数据库和数据表的管理)
  3. Java中组合、继承与代理之间的关系。
  4. QT安装配置是注意事项
  5. C#生成新浪微博短网址 示例源码
  6. MyISAM表加字段的特殊方法
  7. 用border画三角形
  8. Gmail邮箱添加域名解析
  9. 使用json-lib进行Java和JSON之间的转换
  10. 请问 CType和DirectCast函数有何区别