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]特性。

    好了,就到这里吧。

  • 相关阅读:
    windows 远程连接报错
    这30类CSS选择器 你必须记在脑袋里!
    Print to the console in django without UnicodeEncodeErrors
    基于md5的解决js,css缓存问题for django
    Django开发经验
    vscode常用的插件
    点击时添加不同的类
    jQuery 点击空白,隐藏元素
    多功能日历插件:Kalendae
    jQuery中的data()方法
  • 原文地址:https://www.cnblogs.com/chenlinzhi/p/5246212.html
Copyright © 2011-2022 走看看