基于令牌的身份验证

基于令牌的身份验证主要区别于以前常用的常用的基于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令牌的身份验证的更多相关文章

  1. 在ASP.NET Web API 2中使用Owin OAuth 刷新令牌(示例代码)

    在上篇文章介绍了Web Api中使用令牌进行授权的后端实现方法,基于WebApi2和OWIN OAuth实现了获取access token,使用token访问需授权的资源信息.本文将介绍在Web Ap ...

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

    转载地址:ASP.NET Web API 2 中的属性路由使用

  3. 在ASP.NET Web API项目中使用Hangfire实现后台任务处理

    当前项目中有这样一个需求:由前端用户的一个操作,需要触发到不同设备的消息推送.由于推送这个具体功能,我们采用了第三方的服务.而这个服务调用有时候可能会有延时,为此,我们希望将消息推送与用户前端操作实现 ...

  4. ASP.NET Web API 2 中的特性路由

    ASP.NET MVC 5.1 开始已经支持基于特性的路由(http://attributerouting.net),ASP.NET WEB API 2 同时也支持了这一特性. 启用特性路 由只需要在 ...

  5. ASP.NET Web API 2中的错误处理

    前几天在webapi项目中遇到一个问题:Controller构造函数中抛出异常时全局过滤器捕获不到,于是网搜一把写下这篇博客作为总结. HttpResponseException 通常在WebAPI的 ...

  6. [翻译]ASP.NET Web API 2 中的全局错误处理

    目录 已存在的选项 解决方案预览 设计原则 什么时候去用 方案详情 示例 附录: 基类详情 原文链接 Global Error Handling in ASP.NET Web API 2 由于翻译水平 ...

  7. (转)【ASP.NET Web API】Authentication with OWIN

    概述 本文说明了如何使用 OWIN 来实现 ASP.NET Web API 的验证功能,以及在客户端与服务器的交互过程中,避免重复提交用户名和密码的机制. 客户端可以分为两类: JavaScript: ...

  8. ASP.NET Web API实现微信公众平台开发(一)服务器验证

    最近朋友的微信公众号准备做活动,靠固定的微信公众平台模版搞定不了,于是请我代为开发微信后台.鉴于我也是第一次尝试开发微信后台,所以也踩了不少坑,此系列博客将会描述微信公众号各项功能的实现. 先决条件 ...

  9. 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 ...

随机推荐

  1. JavaScript函数式编程究竟是什么?

    摘要: 理解函数式编程. 作者:前端小智 原文:JS中函数式编程基本原理简介 Fundebug经授权转载,版权归原作者所有. 在长时间学习和使用面向对象编程之后,咱们退一步来考虑系统复杂性. 在做了一 ...

  2. itextpdf5操作表格

    下面是一些对表格排版的常用方法,是在制作pdf的时候通过查看ipa和一些博客积累下来的. 包括,表格的宽度,对齐方式,表的页眉页脚,前后间距,padding: 单元格对齐方式,线条设置,段落于单元格之 ...

  3. 【IDE_IntelliJ IDEA】idea主题设置

    参考博文: IDEA 炫酷的主题字体颜色设置 idea主题下载

  4. docker仓库资源的地址修改

    docker仓库资源的地址修改 1.新增或者修改/etc/docker目录下的daemon.json文件 样例文件如下 { "registry-mirrors": ["h ...

  5. 网络流之最大流EK --- poj 1459

    题目链接 本篇博客延续上篇博客(最大流Dinic算法)的内容,此次使用EK算法解决最大流问题. EK算法思想:在图中搜索一条从源点到汇点的扩展路,需要记录这条路径,将这条路径的最大可行流量 liu 增 ...

  6. DNS解惑之资源记录(2)

    1.区域解析库 每个域都要维护一个区域解析库,而区域解析库都是由一条条的记录组成的,而每一条记录就被称为资源记录(resource  record  RR). 我们知道大多数域名下面都不仅仅有www服 ...

  7. 张兴盼-201871010131《面向对象程序设计(Java)》第七周学习总结

    张兴盼-201871010131<面向对象程序设计(Java)>第七周学习总结 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个 ...

  8. 【转】前后端分离的项目如何部署发布到Linux

    前后端分离的项目如何部署发布到Linux 前期准备 1.服务器的基本配置信息2.本机远程连接服务器的工具(xshell.xftp或者mobaXterm等等,看你自己喜欢) 第一步:部署环境 1.安装j ...

  9. SpringCloud介绍(一)

    Spring Cloud 是一套完整的微服务解决方案,基于 Spring Boot 框架,准确的说,它不是一个框架,而是一个大的容器,它将市面上较好的微服务框架集成进来,从而简化了开发者的代码量. 一 ...

  10. Linux SSH建立连接过程分析

    https://blog.csdn.net/qwertyupoiuytr/article/details/71213463 SSH建立连接的过程主要分为下面几个阶段: SSH协议版本协商阶段.SSH目 ...