日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lin-cms-dotnetcore.是如何方法级别的权限控制(API级别)的

發布時間:2023/12/4 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lin-cms-dotnetcore.是如何方法级别的权限控制(API级别)的 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

方法級別的權限控制(API級別)

Lin的定位在于實現一整套 CMS的解決方案,它是一個設計方案,提供了不同的后端,不同的前端,而且也支持不同的數據庫

目前官方團隊維護 lin-cms-vue,lin-cms-spring-boot,lin-cms-koa,lin-cms-flask 社區維護了 lin-cms-tp5,lin-cms-react,lin-cms-dotnetcore,即已支持vue,react二種前端框架,java,nodejs,python,php,c#等五種后端語言。

  • 直接上lin-cms-dotnetcore的demo?http://vvlog.baimocore.cn/#/post/5ecf592e-cc24-9f01-004e-6c0a548f2784

  • http://cms.baimocore.cn/

  • 用戶名:admin

  • 密碼:123qwe

下面我們來講一下.NET?Core這個項目中權限控制的實現。

對于CMS來說,一個完善的權限模塊是必不可少的,是系統內置實現的。為了更加簡單地理解權限,我們先來理解一下ASP.NET?Core有哪些權限控制。

1.AuthorizeAttribute的作用?

這個特性標簽授權通過屬性參數配置,可應用于控制器或操作方法上,對用戶的身份進行驗證。

如果沒有授權,會返回403狀態碼,我們可以通過重寫,來實現返回JSON字符串,讓前臺提示。前提是請求中間件配置了如下二行。

  • app.UseAuthentication();?認證,明確是誰在操作,認證方式如用戶名密碼,登錄后,可以得到一個token,或者寫入cookies,這樣可以確定這個用戶是誰

  • app.UseAuthorization();?授權中間件,明確你是否有某個權限。在http請求時,中間件會在帶有權限特性標簽?[Authorize]?的操作,進行權限判斷,包括角色,策略等。

該控制器下的操作都必須經過身份驗證,

[Authorize] public class AccountController : Controller {public ActionResult Login(){}public ActionResult Logout(){} }

這樣只顯示單個方法必須應用授權。

public class AccountController : Controller {public ActionResult Login(){}[Authorize]public ActionResult Logout(){} }

如果我們通過AllowAnonymous特性標簽去掉身份驗證。Login方法無須進行驗證。即可匿名訪問。

[Authorize] public class AccountController : Controller {[AllowAnonymous]public ActionResult Login(){}public ActionResult Logout(){} }
  • 基于角色的授權

  • 我們可以通過給這個特性標簽加參數,配置,某個方法,控制器是否有這個角色,如果有此角色才能訪問這些資源。

    單個角色

    [Authorize(Roles = "Administrator")] public class AdministrationController : Controller { }

    多個角色,我們可以這樣配置,即用逗號分隔。用戶有其中一個角色即可訪問。

    [Authorize(Roles = "HRManager,Finance")] public class SalaryController : Controller { }

    當某個方法必須同時有二個角色怎么辦呢。該控制器只有同時有PowerUser,和ControlPanelUser的角色才能訪問這些資源了。

    [Authorize(Roles = "PowerUser")] [Authorize(Roles = "ControlPanelUser")] public class ControlPanelController : Controller { }
    • 3.更多。請看官網?https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/roles?view=aspnetcore-3.1

    更多該特性標簽的介紹,也可參考官網,這里就不展開了。

    那這個角色,到底在哪配置的??

    登錄時生成的Token,是基于JWT的,其中的Claim的type為ClaimTypes.Role(枚舉值),角色名稱為字符串,與特性標簽中的Roles屬性值相同。如

    new Claim(ClaimTypes.Role, "Administrator");

    有多個角色時,List<Claim>?多加幾個?new Claim(ClaimTypes.Role, "PowerUser");?也是支持的。user為用戶信息,LinGroups為當前用戶的分組(多個)

    即如下代碼示例,多個分組(角色)

    var claims = new List<Claim>() {new Claim(ClaimTypes.NameIdentifier, user.Email ?? ""),new Claim(ClaimTypes.GivenName, user.Nickname ?? ""),new Claim(ClaimTypes.Name, user.Username ?? ""), };user.LinGroups?.ForEach(r =>{claims.Add(new Claim(ClaimTypes.Role, r.Name));});

    AuthorizeAttribute源碼

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]public class AuthorizeAttribute : Attribute, IAuthorizeData{public AuthorizeAttribute(){}public AuthorizeAttribute(string policy){this.Policy = policy;}public string Policy { get; set; }public string Roles { get; set; }public string AuthenticationSchemes { get; set; }}

    我們可以看到,它繼承了Attribute,說明這是一個特性標簽,IAuthorizeData是一個接口,有這三個屬性,約束了 一個規范,即有角色Roles,有策略Policy,有身份驗證方案AuthenticationSchemes,該特性支持Class,支持方法,該特性標簽支持多個共用,該特性標簽支持被繼承。

    基于角色的授權和基于聲明的授權是一種預配置的策略,即固定的角色,固定的Claims驗證。

    我們可以基于自定義策略的實現更多的權限驗證或某些規則驗證。

    AuthorizeAttribute能做的權限控制如下

    • 基于角色級別的權限控制(多個角色,單個角色)

    • 基于聲明的授權:可自定義聲明特性。

    • 基于策略的授權:

    lin-cms-dotnetcore中的權限設計

    說了這么多官方提供的,我們講一下lin-cms-dotnetcore中的權限設計

    完整的表結構如下?https://luoyunchong.github.io/vovo-docs/dotnetcore/lin-cms/table.html

    LinCmsAuthorizeAttribute

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]public class LinCmsAuthorizeAttribute : Attribute, IAsyncAuthorizationFilter{public string Permission { get; }public string Module { get; }public LinCmsAuthorizeAttribute(string permission, string module){Permission = permission;Module = module;}public async Task OnAuthorizationAsync(AuthorizationFilterContext context){ClaimsPrincipal claimsPrincipal = context.HttpContext.User;if (!claimsPrincipal.Identity.IsAuthenticated){HandlerAuthenticationFailed(context, "認證失敗,請檢查請求頭或者重新登陸", ErrorCode.AuthenticationFailed);return;}IAuthorizationService authorizationService = (IAuthorizationService)context.HttpContext.RequestServices.GetService(typeof(IAuthorizationService));AuthorizationResult authorizationResult = await authorizationService.AuthorizeAsync(context.HttpContext.User, null, new OperationAuthorizationRequirement() { Name = Permission });if (!authorizationResult.Succeeded){HandlerAuthenticationFailed(context, $"您沒有權限:{Module}-{Permission}", ErrorCode.NoPermission);}}public void HandlerAuthenticationFailed(AuthorizationFilterContext context, string errorMsg, ErrorCode errorCode){context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;context.Result = new JsonResult(new UnifyResponseDto(errorCode, errorMsg, context.HttpContext));}}

    上面的實現非常簡單,LinCmsAuthorizeAttribute繼承于Attribute,說明是一個特性標簽,有二個屬性Permission,Module,代表權限名,模塊名(用于區分哪個功能模塊),然后將權限名稱轉化為OperationAuthorizationRequirement,然后調用authorizationService中的方法AuthorizeAsync來完成授權。

    接下來,我們在控制器上使用LinCmsAuthorizeAttribute,那么我們

    [Route("cms/admin/group")] [ApiController] public class GroupController : ControllerBase {private readonly IGroupService _groupService;public GroupController(IGroupService groupService){_groupService = groupService;}[HttpGet("all")][LinCmsAuthorize("查詢所有權限組","管理員")]public Task<List<LinGroup>> GetListAsync(){return _groupService.GetListAsync();}[HttpGet("{id}")][LinCmsAuthorize("查詢一個權限組及其權限","管理員")]public async Task<GroupDto> GetAsync(long id){GroupDto groupDto = await _groupService.GetAsync(id);return groupDto;}[HttpPost][LinCmsAuthorize("新建權限組","管理員")]public async Task<UnifyResponseDto> CreateAsync([FromBody] CreateGroupDto inputDto){await _groupService.CreateAsync(inputDto);return UnifyResponseDto.Success("新建分組成功");}[HttpPut("{id}")][LinCmsAuthorize("更新一個權限組","管理員")]public async Task<UnifyResponseDto> UpdateAsync(long id, [FromBody] UpdateGroupDto updateGroupDto){await _groupService.UpdateAsync(id, updateGroupDto);return UnifyResponseDto.Success("更新分組成功");}[HttpDelete("{id}")][LinCmsAuthorize("刪除一個權限組","管理員")]public async Task<UnifyResponseDto> DeleteAsync(long id){await _groupService.DeleteAsync(id);return UnifyResponseDto.Success("刪除分組成功");}}

    這樣在方法上已經加了權限的標簽,但我們怎么得到系統中的所有權限,讓用戶配置呢。?獲取控制器及方法特性標簽。本質上,是通過反射,掃描當前程序集,會獲取到一個List,我們可以在系統啟動時把這些數據存到數據庫中。

    最新的方式是采用此方法,原理都相同。name,module唯一值。存入lin_permission表中,這時就有id值了。lin_group_permission就能用分組關聯了。

    public async Task SeedAsync() {List<PermissionDefinition> linCmsAttributes = ReflexHelper.GeAssemblyLinCmsAttributes();List<LinPermission> insertPermissions = new List<LinPermission>();List<LinPermission>allPermissions=await _permissionRepository.Select.ToListAsync();linCmsAttributes.ForEach(r =>{bool exist = allPermissions.Any(u => u.Module == r.Module && u.Name == r.Permission);if (!exist){insertPermissions.Add(new LinPermission(r.Permission, r.Module));}});await _permissionRepository.InsertAsync(insertPermissions);}

    實現方法級的權限控制源碼解析

    上面的LinCmsAttribute調用了IAuthorizationService類中的方法,那他是什么呢。原理可以看這個文章ASP.NET Core 認證與授權[7]:動態授權中的自定義授權過濾器

    我們需要了解一下這些類/接口/抽象類

    • IAuthorizationService(interface)

    • AuthorizationService(class)

    • IAuthorizationHandler(interface)

    • AuthorizationHandler<TRequirement>(abstract class)

    • PermissionAuthorizationHandler(class 自定義的類,繼承AuthorizationHandler)

    總結調用鏈如下

    LinCmsAuthorizeAttribute(繼承了IAsyncAuthorizationFilter的特性標簽) 調用了----> IAuthorizationService中的AuthorizeAsync方法 調用了----> IAuthorizationHandler中的HandleAsync 調用了----> AuthorizationHandler中的HandleRequirementAsync抽象方法 相當于調用----> PermissionAuthorizationHandler類中的實現方法HandleRequirementAsync 調用了----> IPermissionService類中的CheckPermissionAsync方法。 調用了----> IAuditBaseRepository<LinPermission,long> IAuditBaseRepository<LinGroupPermission, long> 使用FreeSql,判斷當前用戶所在分組是否擁有此權限。

    IAuthorizationService是什么呢。我們可以理解為,驗證當前用戶是否擁有對應的資源權限。系統默認實現了該方法

    public interface IAuthorizationService {Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements);Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName); }

    AuthorizationService是什么呢.他實現了IAuthorizationService接口. 通過源碼我們知道,它調用?await authorizationHandler.HandleAsync(authContext);

    public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user,object resource,IEnumerable<IAuthorizationRequirement> requirements) {if (requirements == null)throw new ArgumentNullException(nameof (requirements));AuthorizationHandlerContext authContext = this._contextFactory.CreateContext(requirements, user, resource);foreach (IAuthorizationHandler authorizationHandler in await this._handlers.GetHandlersAsync(authContext)){await authorizationHandler.HandleAsync(authContext);if (!this._options.InvokeHandlersAfterFailure){if (authContext.HasFailed)break;}}AuthorizationResult authorizationResult = this._evaluator.Evaluate(authContext);if (authorizationResult.Succeeded)this._logger.UserAuthorizationSucceeded();elsethis._logger.UserAuthorizationFailed();return authorizationResult; }

    IAuthorizationHandler 僅一個接口。

    public interface IAuthorizationHandler {/// <summary>/// Makes a decision if authorization is allowed./// </summary>/// <param name="context">The authorization information.</param>Task HandleAsync(AuthorizationHandlerContext context); }

    AuthorizationHandler,它繼承IAuthorizationHandler?而且他是一個抽象類,默認實現了HandleAsync方法,子類只用實現HandleRequirementAsync即可。

    public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandlerwhere TRequirement : IAuthorizationRequirement{public virtual async Task HandleAsync(AuthorizationHandlerContext context){foreach (TRequirement requirement in context.Requirements.OfType<TRequirement>())await this.HandleRequirementAsync(context, requirement);}protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context,TRequirement requirement);}

    我們就可以繼承AuthorizationHandler,子類實現從數據庫中取數據做對比,其中泛型參數使用系統內置的一個只有Name的類OperationAuthorizationRequirement,當然,如果我們需要更多的參數,可以繼承IAuthorizationRequirement,增加更多的參數。

    判斷當前用戶是否不為null,當調用CheckPermissionAsync,判斷是否有此權限。

    public class PermissionAuthorizationHandler : AuthorizationHandler<OperationAuthorizationRequirement>{private readonly IPermissionService _permissionService;public PermissionAuthorizationHandler(IPermissionService permissionService){_permissionService = permissionService;}protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement){Claim userIdClaim = context.User?.FindFirst(_ => _.Type == ClaimTypes.NameIdentifier);if (userIdClaim != null){if (await _permissionService.CheckPermissionAsync(requirement.Name)){context.Succeed(requirement);}}}}

    另外我們還需要把這個Handler注入到我們的DI中,在ConfigureServices中替換如下服務

    services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();

    其中的PermssionAppService中的實現,檢查當前登錄的用戶的是否有此權限

    public async Task<bool> CheckPermissionAsync(string permission) {long[] groups = _currentUser.Groups;LinPermission linPermission = await _permissionRepository.Where(r => r.Name == permission).FirstAsync();bool existPermission = await _groupPermissionRepository.Select.AnyAsync(r => groups.Contains(r.GroupId) && r.PermissionId == linPermission.Id);return existPermission; }

    更多參考

    • ASP.NET Core 認證與授權[1]:初識認證

    開源地址

    • 后端接口Gitee 鏈接?https://gitee.com/igeekfan/lin-cms-dotnetcore

    • 后端接口GitHub 鏈接?https://github.com/luoyunchong/lin-cms-dotnetcore

    • 管理端UI?https://github.com/luoyunchong/lin-cms-vue

    • 用戶端UI?https://github.com/luoyunchong/lin-cms-vvlog

    總結

    以上是生活随笔為你收集整理的lin-cms-dotnetcore.是如何方法级别的权限控制(API级别)的的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 在线观看国产三级 | 久久久精品视频免费 | www夜夜| 成全世界免费高清观看 | 91麻豆视频 | 日韩国产在线观看 | 色爱综合区 | 91精品网 | 国产91精品久久久久久久 | 欧美特黄色片 | 久久综合一区二区三区 | 手机在线观看免费av | 午夜不卡久久精品无码免费 | 九九久久久久 | 日本黄色不卡视频 | 超碰青青操 | 西野翔夫の目の前で犯在线 | 四虎成人在线视频 | 少妇人妻偷人精品无码视频 | 色射射| 国产性猛交xxxⅹ交酡全过程 | 中文字幕精品一二三四五六七八 | 日韩毛片在线 | 国产又粗又黄又爽又硬 | 91成人免费视频 | 激情欧美综合 | 天天爽夜夜爽夜夜爽 | 国产香蕉97碰碰碰视频在线观看 | 亚洲高潮av | 国产二级视频 | 伊人激情影院 | 欧美一区综合 | 久久人人爽人人人人片 | 国产性70yerg老太 | 久久在线| 少妇被黑人到高潮喷出白浆 | 日本一区二区三区视频在线播放 | 新天堂网 | 91一区二区视频 | 99成人在线视频 | 亚洲av成人一区二区国产精品 | 欧美大喷水吹潮合集在线观看 | 黄色录像二级片 | 国产精品国产av | 黑人精品欧美一区二区蜜桃 | 欧美日韩国产伦理 | 日韩三区在线观看 | 中文字幕久久久久久久 | 国产精品久久久一区 | 中国老熟女重囗味hdxx | 亚洲四区 | 小敏的受孕日记h | 黄色网址在线免费 | 精东影业一区二区三区 | 91成人高清 | 欧美成免费 | 亚洲欧美精品一区二区 | 亚洲精品久久久久 | 中文字幕av在线免费 | 成人午夜在线播放 | 美女的诞生免费观看在线高清 | 美女视频黄a视频全免费观看 | 富二代成人短视频 | 一区二区三区在线观 | 东京av男人的天堂 | 97看片网| 男人的网站在线观看 | 欧亚免费视频 | 偷拍精品一区二区三区 | 91av视频在线观看 | 欧美成人一区二区在线 | 丝袜美腿亚洲综合 | 香蕉福利 | 在线观看黄色网 | 免费在线观看日韩av | 男人插女人免费视频 | 日韩黄色免费看 | 小萝莉末成年一区二区 | 日日夜夜欧美 | 好吊色一区二区三区 | 欧美在线视频二区 | 国产浮力第一页 | 亚洲成人午夜影院 | 欧美日韩中文国产一区发布 | 成年激情网 | 精品人伦一区二区三电影 | 瑟瑟久久| free性护士vidos猛交 | wwwxxx国产| 69av网| 亚洲午夜无码久久 | 国产精品久久久久久免费 | 国产日韩免费视频 | 亚洲第一女人av | 在线五月天 | 最近的中文字幕在线看视频 | 成人一级在线 | 成人免费一级片 | 成人h动漫精品一区二区下载 |