zoukankan      html  css  js  c++  java
  • Web API 基于ASP.NET Identity的Basic Authentication

      今天给大家分享在Web API下,如何利用ASP.NET Identity实现基本认证(Basic Authentication),在博客园子搜索了一圈Web API的基本认证,基本都是做的Forms认证,很少有Claims认证(声明式认证),而我们在用ASP.NET Identity实现登录,认证,授权的时候采用的是Claims认证。

      在Web API2.0中认证接口为IAuthenticationFilter,我们只需实现该接口就行。创建BasicAuthenticationAttribute抽象基类,实现IAuthenticationFilter接口:

     1 public abstract class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter 
     2     {
     3         protected abstract Task<IPrincipal> AuthenticateAsync(string userName, string password, HttpAuthenticationContext context,
     4             CancellationToken cancellationToken);
     5         public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
     6         {
     7             context.Principal = null;
     8             AuthenticationHeaderValue authenticationHeader = context.Request.Headers.Authorization;
     9             if (authenticationHeader != null && authenticationHeader.Scheme == "Basic")
    10             {
    11                 if (!string.IsNullOrEmpty(authenticationHeader.Parameter))
    12                 {
    13                     Tuple<string, string> data = GetUserNameAndPassword(authenticationHeader.Parameter);
    14                     context.Principal = await AuthenticateAsync(data.Item1, data.Item2,context, cancellationToken);
    15                 }
    16             }
    17 
    18             if (context.Principal == null)
    19             {
    20                 context.ErrorResult = new UnauthorizedResult(new[] {new AuthenticationHeaderValue("Basic")},
    21                     context.Request);
    22             }
    23         }
    24         public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    25         {
    26             return Task.FromResult(0);
    27         }
    28         public bool AllowMultiple
    29         {
    30             get { return false; }
    31         }
    32         private Tuple<string, string> GetUserNameAndPassword(string authenticationParameter)
    33         {
    34             if (!string.IsNullOrEmpty(authenticationParameter))
    35             {
    36                 var data = Encoding.ASCII.GetString(Convert.FromBase64String(authenticationParameter)).Split(':');
    37                 return new Tuple<string, string>(data[0], data[1]);
    38             }
    39             return null;
    40         }
    41     }
    View Code

    其中Task<IPrincipal> AuthenticateAsync(string userName, string password, HttpAuthenticationContext context, CancellationToken cancellationToken)方法为抽象方法,用户可以重载实现自己的认证方式,Forms认证,Windows认证,Claims认证等等都可以。

     AuthenticationHeaderValue authenticationHeader= context.Request.Headers.Authorization用于获取HTTP请求头部的认证信息。

     authenticationHeader.Scheme == "Basic"用于指定认证模式为基本认证。

    authenticationHeader.Parameter用户获取用户加密过后的用户名和密码。

    如果认证不为空,且是Basic认证,头部参数不为空,则调用认证的具体代码,如果认证不通过,则调用HTTP认证上下文的ErroResult属性:

     context.ErrorResult = new UnauthorizedResult(new[] {new AuthenticationHeaderValue("Basic")},context.Request);设置了该属性,浏览器则自动弹出用户登录的窗口。要想浏览器自动弹出登录窗口,必须在WebApiConfig配置类中指定令牌身份验证,即调用如下代码:config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));否则无法弹出登录窗体。

    Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)方法在认证通过成功和失败后都会调用此方法,你可以在这里实现自己想要的逻辑,比如设置context.ErrorResult属性,在这里就不做处理了,因为AuthenticateAsync方法已经做了处理了。

    GetUserNameAndPassword方法用于处理加密过后的用户名和密码。

    接下来就是实现自己的认证逻辑了,这里采用Asp.net Identity的Claims认证。

     1  public class IdentityBasicAuthenticationAttribute : BasicAuthenticationAttribute
     2     {
     3         protected override async Task<IPrincipal> AuthenticateAsync(string userName, string password,
     4             HttpAuthenticationContext context, CancellationToken cancellationToken)
     5         {
     6             IPrincipal principal = null;
     7             var userManager = context.Request.GetOwinContext().GetUserManager<AppUserManager>();
     8             var user = await userManager.FindAsync(userName, password);
     9             if (user != null)
    10             {
    11                 ClaimsIdentity identity =
    12                     await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
    13                 ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity);
    14                 principal = claimsPrincipal;
    15             }
    16             return principal;
    17         }
    18     }
    View Code

    var userManager = context.Request.GetOwinContext().GetUserManager<AppUserManager>()用于当前的用户管理器,用户的增删改查操作都依赖于此对象。

    var user = await userManager.FindAsync(userName, password)用户根据用户名和密码找到用户。

    ClaimsIdentity identity = await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)创建用户,然后 通过ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity)创建声明,并且返回认证类型。

    至于如何创建UserManager,如何通过Entityframwork来生成Asp.net Identity用户,角色和认证相关表,这里就不多说了,园子里面多的去了。

    记得在登录代码中把用户名和密码加密后放到Cookie中,登陆后,在访问某个需要认证的Action时候记得在HTTP请求头部中写入Cookie信息,这样认证的Filter才能取到用户信息,登录创建Cookie代码片段如下:

                CookieHeaderValue cookie = new CookieHeaderValue("userToken", authorization)
                        {
                            Path = "/",
                            Domain = Request.RequestUri.Host,
                            Expires = DateTimeOffset.Now.AddDays(7)
                        };
                        responseMessage.Headers.AddCookies(new[] {cookie});
    

     客户短AJax调用需要验证的Action方法如下:

        function ajaxOp(url, type, data) {
            $.ajax({
                url: url,
                type: type,
                data: data,
                beforeSend: function(xhr) {
                    xhr.setRequestHeader('Authorization', 'Basic ' + $.cookie("userToken"));
                }
            });
        }
    

     其中  beforeSend: function(xhr) {xhr.setRequestHeader('Authorization', 'Basic ' + $.cookie("userToken"))属性设置用于获取Cookie信息放到请求头部。

    需要调用的Action记得加上  [IdentityBasicAuthentication]特性。

    好了,就到这里吧。

  • 相关阅读:
    python note 30 断点续传
    python note 29 线程创建
    python note 28 socketserver
    python note 27 粘包
    python note 26 socket
    python note 25 约束
    Sed 用法
    python note 24 反射
    python note 23 组合
    python note 22 面向对象成员
  • 原文地址:https://www.cnblogs.com/chenlinzhi/p/5246212.html
Copyright © 2011-2022 走看看