上一篇已經完成了「身份驗證」,若是隻是想簡單的實現基於角色的權限管理,咱們基本上不用寫代碼,微軟已經提供了authorize特性,直接用就行。html
配置Authorizeweb
比較簡單,直接上代碼api
using System.Collections.Generic; using System.Net.Http; using System.Security.Claims; using System.Web.Http; using webapi.Common; namespace webapi.example { [RoutePrefix("api/security")] public class SecurityTestController : ApiController { /// <summary> /// 經過get請求裏傳過來的值生成token /// </summary> /// <returns></returns> [Route("token"),HttpGet] public IHttpActionResult GetToken() { var dic=new Dictionary<string,object>(); foreach (var queryNameValuePair in Request.GetQueryNameValuePairs()) { dic.Add(queryNameValuePair.Key,queryNameValuePair.Value); } var token=new JWTHelper().Encode(dic, "shengyu",30); return Ok(token); } /// <summary> /// 返回token里加密的信息 /// </summary> /// <returns></returns> [Route("GetUserInfoFromToken"),HttpGet] public IHttpActionResult GetUser() { var user = (ClaimsPrincipal)User; var dic=new Dictionary<string,object>(); foreach (var userClaim in user.Claims) { dic.Add(userClaim.Type,userClaim.Value); } return Ok(dic); } #region 硬編碼的方式實現簡單的權限控制 /// <summary> /// 只有某種角色的用戶纔有權限訪問 /// </summary> /// <returns></returns> [Route("byCode/onlyRoles"), Authorize(Roles = "admin,superAdmin"),HttpGet] public IHttpActionResult OnlyRoles_SetByCode() { return Ok("OnlyRoles_SetByCode,僅管理員能訪問"); } /// <summary> /// 只有某幾個用戶纔有權限訪問 /// </summary> /// <returns></returns> [Route("byCode/onlyUsers"), Authorize(Users = "張三,李四"),HttpGet] public IHttpActionResult OnlyUsers_SetByCode() { return Ok("OnlyRoles_SetByCode,僅張三和李四才能訪問"); } #endregion } }
Authorize特性有Roles和Users兩個屬性,設置這兩個屬性的值及能夠控制哪些角色/用戶有權限訪問。Authorize特性能夠用於修飾類或是方法,若是整個控制器都要用權限控制,則修飾這個控制器類,不然只修飾在某個接口上。若是控制器被修飾了但又要排除某一個action,可用AllowAnonymous特性進行排除。安全
獲取token框架
如今獲取一個token,這個token裏包含了「角色爲admin」的信息,以下ide
用上一篇:webapi框架搭建-安全機制-身份驗證(二)裏的獲取token的接口獲取一個role爲admin的tokenpost
請求須要權限的接口編碼
請求須要角色爲admin或是superAdmin的接口SecurityTestController.OnlyRoles_SetByCode(),注意將上一步生成的token放到http request的header裏加密
你可嘗試在「獲取token"步驟裏生成非admin角色的token,那麼在這一步裏會出現受權失敗的錯誤,以下圖spa
一樣原理,在」獲取token"步驟裏user設置成「張三」或「李四」時,就能夠用此token訪問SecurityTestController.OnlyUsers_SetByCode()接口了。
在實際開發中,獲取token的接口(即方法SecurityTestController.GetToken())裏的代碼一般寫在用戶登陸接口裏,用戶經過用戶名和密碼登陸成功後,接口訪問一個token給客戶端,之後客戶端的每次接口請求都在headers裏帶上這個token。微軟提供的默認authorize特性在小項目和中型的對權限控制沒有複雜要求的項目裏已經夠用了。缺點是項目開發前得肯定好業務的各類角色,由於要以「硬編碼」的方式寫在接口方法上。後期若是要修改一個接口的所屬角色,只有從新修改代碼。
若是要實現更加可控的基於角色的權限控制,只有本身寫Authorize filter。下面介紹如何寫本身的authorize filter。
可經過繼承下面三個對象之一去寫本身的authorize filter
即:AuthorizeAttribute、AuthorizationFilterAttribute、IAuthorizationFilter,三者的關係以下圖
我採用繼承AuthorizeAttribute,並重寫IsAuthorized方法,代碼以下
using System.Net; using System.Net.Http; using System.Web.Http; using System.Web.Http.Controllers; namespace webapi.Security { /// <summary> /// Role Basic AuthorizeAttribute(基於角色的受權) /// </summary> public class RBAuthorizeAttribute:AuthorizeAttribute { protected override bool IsAuthorized(HttpActionContext actionContext) { // 下在可替換成本身的受權邏輯代碼 return base.IsAuthorized(actionContext); } protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) { actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "未受權"); } } }
RBAuthorize特性和Authorize特性用法是同樣的,再也不重複。後續的博客裏會引入基於角色的權限管理的表結構,並在IsAuthorized方法裏寫受權邏輯。