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

好了,就到這里吧。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM