OAuth在WebApi中的使用,前后台分離的調用方式


前段時間由於公司架構服務層向WebApi轉換,就研究了OAuth在WebApi中的使用,這中間遇到了很多坑,在此記錄一下OAuth的正確使用方式。

1、  OAuth是做什么的?

  在網上瀏覽時,大家都見過這樣的功能:網站A提供了第三方登錄服務,比如使用新浪微博、QQ賬戶登錄。用戶使用第三方賬戶登陸后,第三方返回Token給網站A,當網站A調用第三方服務請求登錄用戶信息時需傳遞該Token給第三方,第三方才允許該服務請求。之后的每次請求無需再次認證,直接使用該Token即可。這就是OAuth的典型應用。

2、  簡單使用介紹 (具體使用OAuth的方法請參考:在ASP.NET中基於Owin OAuth使用Client Credentials Grant授權發放Token)

  2.1、用戶登錄的過程即是獲取Token的過程,前端用戶登錄示例代碼如下:

 1 $.ajax({  2             type: "POST",  3             url: api_address + "token", //api_address為WebApi服務地址,由於OAuth的使用中設置了屬性TokenEndpointPath = new PathString("/token"),所以請求到“token”鏈接時即可自動進入認證流程。
 4             data: { grant_type: "password", username: username, password: password, ran: Math.random() },//傳遞用戶名、密碼、認證方式
 5             dataType: "json",  6  success: function (result) {  7                 if (result.access_token && result.access_token.length > 0) {  8                       //result.access_token即是有效的服務調用憑證,可以把該值存入到Cookie中,以備下次使用。
 9 callback(1, "登錄成功。"); 10  } 11                 else { 12                     callback(0, "未知錯誤!"); 13  } 14  }, 15  error: function (XMLHttpRequest, textStatus, errorThrown) { 16                 callback(0, XMLHttpRequest.responseJSON.error); 17  } 18         });
登錄代碼

  2.2、當認證方式為password時,已下方法為認證流程中的一步。(認證通過才會返回Token)

 1 public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)  2 {  3     var username= context.UserName;  4     var password=context.Password;  5     if(用戶名與密碼不合法)  6  {  7     context.setError(“用戶名或密碼錯誤!”);//認證不通過
 8  }  9     else
10  { 11     var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType); 12     oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 13     //可以加入用戶信息及其他必要信息到Token中,以便在api服務中使用(使用中HttpContext.Current.User.Identity即為oAuthIdentity對象,WebApi的Controller中可直接使用User.Identity)。
14     oAuthIdentity.AddClaim(new Claim("UserID", user.UserID.ToString())); 15     var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties()); 16       context.Validated(ticket);//認證通過
17  } 18     return base.GrantResourceOwnerCredentials(context); 19 }    
認證代碼

3、 已經獲取了Token,如何使用?

  網上的大部分示例都是使用HttpClient調用的方式,而前后端的完全分離作為一種發展趨勢,我們需要Jquery的調用方式。

 1 $.ajax({  2             type: “method”,//get,post,put,delete
 3             url:api_address + “api/Test”,//如果調用webapi中的TestController
 4  data: {data},  5             dataType: "json",  6  headers: {  7                 "Authorization": "Bearer " + “token” //把登錄獲取的Token加入到http請求頭中
 8  },  9  success: function (result) { 10  callback(result); 11  }, 12  error: function (XMLHttpRequest, textStatus, errorThrown) { 13                 //。。。。。。
14  } 15 });
調用Api

4、Api的訪問權限該如何做?

  認證中我們把用戶登錄成功作為認證通過的標志,但不同角色的用戶具有不同的訪問權限(個人認為認證中應使用最小權限驗證,如示例中的登錄成功),如何控制有些Controller不能被低權限用戶訪問。

1 [Authorize] 2 public class TestController: ApiController 3 { 4     // GET api/<controller>
5     public HttpResponseMessage Get(int appid) 6  { 7         return null; 8  } 9 }
一個典型的ApiController

  [Authorize]表示訪問該Controller的請求必須經過認證(請求頭中具有Token信息),這里我們可以自定義一個特性去驗證用戶權限,並替換特性AuthorizeAttribute。(這里僅提供思路,具體做法請自己摸索,不保證以下代碼的正確性)

 1 public class CustomeAuthorizeAttribute:System.Web.Http.AuthorizeAttribute  2 {  3         protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)  4  {  5         if(base.IsAuthorized(actionContext))  6  {  7             //這里對用戶的權限進行驗證,actionContext可以獲得請求的是哪一個Controller
 8             var user = HttpContext.Current.User.Identity;//Token中帶有的用戶信息
 9              if (可以訪問) 10  { 11                  return true; 12  } 13              return false; 14  } 15            return false; 16  } 17 } 18                 
示例自定義特性(攔截器)

 


免責聲明!

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



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