【转】在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包,并設置“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令牌的身份验证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地方债一般债和专项债的区别,这些地方赶
- 下一篇: 白户能办高额信用卡么 白户办高额信用卡方