Web Api 2 認證與受權 2

HTTP Message Handler
html

Web Api 2 認證與受權 中講解了幾種實現機制,本篇就詳細講解 Message Handler 的實現方式git

關於 Message Handler 在 request 到 response 過程所處於的位置,能夠參考這裏 HTTP Message Handlersgithub

 

Authentication Message Handlerweb

先看一段實現的代碼,而後再作講解,完整代碼能夠在 Github 上參考,WebApi2.Authenticationjson

 1 using System;
 2 using System.Net;
 3 using System.Net.Http;
 4 using System.Security.Claims;
 5 using System.Threading;
 6 using System.Threading.Tasks;
 7 // WebPrint.Framework reference https://github.com/LeafDuan/WebPrint/tree/master/WebPrint.Framework
 8 using WebPrint.Framework;
 9 
10 namespace Server.Helper
11 {
12     // references
13     // http://www.codeproject.com/Articles/630986/Cross-Platform-Authentication-With-ASP-NET-Web-API
14     // http://dgandalf.github.io/WebApiTokenAuthBootstrap/
15     public class AuthenticationMessageHandler : DelegatingHandler
16     {
17         protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
18             CancellationToken cancellationToken)
19         {
20             if (request.Headers.Authorization == null)
21             {
22                 var reply = request.CreateResponse(HttpStatusCode.Unauthorized, "Missing authorization token.");
23                 
24                 return Task.FromResult(reply);
25             }
26 
27             try
28             {
29                 var encryptedToken = request.Headers.Authorization.Parameter;
30                 var token = Token.Decrypt(encryptedToken);
31                 //bool isValidUser
32                 var isIpMathes = token.ClientIp.EqualTo(request.GetClinetIp());
33 
34                 if (!isIpMathes)
35                 {
36                     var reply = request.CreateResponse(HttpStatusCode.Unauthorized, "Invalid authorization token");
37                     return Task.FromResult(reply);
38                 }
39 
40                 var principal = new ClaimsPrincipal(new ClaimsIdentity(new[]
41                 {
42                     new Claim(ClaimTypes.Name, token.UserId.ToString())
43                 }, "Basic"));
44 
45                 // authorize attribute 
46                 request.GetRequestContext().Principal = principal;
47             }
48             catch (Exception ex)
49             {
50                 var reply = request.CreateErrorResponse(HttpStatusCode.Unauthorized, ex.Message);
51                 return Task.FromResult(reply);
52             }
53 
54             return base.SendAsync(request, cancellationToken);
55         }
56     }
57 }

實現也是很簡單,經過繼承 DelegatingHandler 重寫 SendAsync 方法實現,整個流程須要的步驟以下:api

1 登陸,經過 api/auth 接收登陸信息,驗證後生成一個 tokenasp.net

2 每次請求判斷  request.Headers.Authorization 參數,看是否攜帶 token (Http Client 將步驟 1 中的 token 設置到 request.Headers.Authorization)ide

3 解析 token,設置請求上下文的 Principal 用於 Authorize 屬性使用oop

基本過程就差很少這三部曲,其中關於 token 的驗證,如是否超時,是否重複,可自行想辦法去實現spa

 

Web Api Config

你們都知道 Message Handler 在 pipeline 裏是在 controller 以前運行,所以請求全部的 Api Controller 都會先執行 handler,所以針對登陸,須要給予額外的照顧,容許匿名訪問,實現方法:handler 能夠是全局的,也能夠是 per router 的,所以此處經過後一種方式實現:

 1 using System.Linq;
 2 using System.Net.Http.Formatting;
 3 using System.Web.Http;
 4 using System.Web.Http.Dispatcher;
 5 using Newtonsoft.Json;
 6 using Server.Helper;
 7 
 8 namespace Server
 9 {
10     public static class WebApiConfig
11     {
12         public static void Register(HttpConfiguration config)
13         {
14             config.MapHttpAttributeRoutes();
15 
16             config.Routes.MapHttpRoute(
17                 name: "Authentication",
18                 routeTemplate: "api/auth",
19                 defaults: new {controller = "account"}
20                 );
21 
22             config.Routes.MapHttpRoute(
23                 name: "DefaultApi",
24                 routeTemplate: "api/{controller}/{id}",
25                 defaults: new {id = RouteParameter.Optional},
26                 constraints: null,
27                 handler: new AuthenticationMessageHandler {InnerHandler = new HttpControllerDispatcher(config)}
28                 );
29 
30             var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
31 
32             jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
33             jsonFormatter.SerializerSettings.ContractResolver = new NHibernateContractResolver();
34         }
35     }
36 }

 

總結

最近匆匆忙忙使用託管在 Owin Self Host 上的 Web Api 2,遇到問題頗多,不少也是匆匆忙忙解決的,這裏也就匆匆忙忙作一個分享。

相關文章
相關標籤/搜索