• Web Api 2 认证与授权 2


    HTTP Message Handler

    Web Api 2 认证与授权 中讲解了几种实现机制,本篇就详细讲解 Message Handler 的实现方式

    关于 Message Handler 在 request 到 response 过程所处于的位置,可以参考这里 HTTP Message Handlers

    Authentication Message Handler

    先看一段实现的代码,然后再做讲解,完整代码可以在 Github 上参考,WebApi2.Authentication

     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 方法实现,整个流程需要的步骤如下:

    1 登录,通过 api/auth 接收登录信息,验证后生成一个 token

    2 每次请求判断  request.Headers.Authorization 参数,看是否携带 token (Http Client 将步骤 1 中的 token 设置到 request.Headers.Authorization)

    3 解析 token,设置请求上下文的 Principal 用于 Authorize 属性使用

    基本过程就差不多这三部曲,其中关于 token 的验证,如是否超时,是否重复,可自行想办法去实现

    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,遇到问题颇多,很多也是匆匆忙忙解决的,这里也就匆匆忙忙做一个分享。

  • 相关阅读:
    <html:form>里的<html:password property="password"/>中的property
    关于validate
    ActionForm的详解
    Struts控制流
    Action的详解
    formValidate输入验证
    在JS里面,取struts的<html:form>标签里面的<html:text property="title"/>值
    ActionMapping的详解
    学习数据结构的网站
    ActionForm本质
  • 原文地址:https://www.cnblogs.com/ranmofang/p/3804263.html
Copyright © 2020-2023  润新知