webapi框架搭建系列博客
上一篇已經完成了“身份驗證”,如果只是想簡單的實現基於角色的權限管理,我們基本上不用寫代碼,微軟已經提供了authorize特性,直接用就行。
Authorize特性的使用方法
配置Authorize
比較簡單,直接上代碼
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”的信息,如下
用上一篇:webapi框架搭建-安全機制-身份驗證(二)里的獲取token的接口獲取一個role為admin的token
請求需要權限的接口
請求需要角色為admin或是superAdmin的接口SecurityTestController.OnlyRoles_SetByCode(),注意將上一步生成的token放到http request的header里
你可嘗試在“獲取token"步驟里生成非admin角色的token,那么在這一步里會出現授權失敗的錯誤,如下圖
同樣原理,在”獲取token"步驟里user設置成“張三”或“李四”時,就可以用此token訪問SecurityTestController.OnlyUsers_SetByCode()接口了。
在實際開發中,獲取token的接口(即方法SecurityTestController.GetToken())里的代碼通常寫在用戶登錄接口里,用戶通過用戶名和密碼登錄成功后,接口訪問一個token給客戶端,以后客戶端的每次接口請求都在headers里帶上這個token。微軟提供的默認authorize特性在小項目和中型的對權限控制沒有復雜要求的項目里已經夠用了。缺點是項目開發前得確定好業務的各種角色,因為要以“硬編碼”的方式寫在接口方法上。后期如果要修改一個接口的所屬角色,只有重新修改代碼。
如果要實現更加可控的基於角色的權限控制,只有自己寫Authorize filter。下面介紹如何寫自己的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方法里寫授權邏輯。