美文网首页架构
7-OAuth2 & OpenID Connect &a

7-OAuth2 & OpenID Connect &a

作者: 俊果果 | 来源:发表于2018-08-25 22:14 被阅读75次

    一、ABAC 简介

    ABAC 即:【Attribute-based Access Control】基于属性的访问控制
    与之对应的,我们有:【Role-based Access Control 】
    可以参考这篇文章权限系统设计模型分析(DAC,MAC,RBAC,ABAC)
    此处不再详细说明

    image.png

    二、Client 使用 ABAC

    1. 修改 IDP
    • Config

    GetIdentityResources方法添加代码

    new IdentityResource("country","Country where the user lives in", new List<string>(){"country"}),
    new IdentityResource("subscriptionlevel","User's subscription level",new List<string>(){"subscriptionlevel"})
    

    GetClients方法中的 AllowedScopes添加

    image.png
    GetUsers 方法中为 Users 添加对应 claim 和 值
    1. 修改 Client
    • Startup
      ConfigureServices方法修改如下:
      添加代码
                services.AddAuthorization(authorizationOptions =>
                {
                    authorizationOptions.AddPolicy(
                        "CanOrderFrame",
                        policyBuilder =>
                        {
                            policyBuilder.RequireAuthenticatedUser();
                            policyBuilder.RequireClaim("country", "Heaven", "CHN");
                            policyBuilder.RequireClaim("subscriptionlevel", "supervip");
                        });
                });
    

    定义一个 Policy:已登录用户并且付费级别为 supervip、国家是 Heaven 或 CHN的才满足条件


    image.png
    image.png
    • 修改 _Layout.cshtml 当用户满足权限时才显示 OrderFrame 按钮
      image.png
    • 修改GalleryController
      OrderFrame 方法添加属性
     [Authorize(Policy = "CanOrderFrame")]
    public async Task<IActionResult> OrderFrame(){...}
    

    再运行,用不同用户登录尝试
    例如,用 Claire 登录时 Debug 输出信息如下

    image.png
    点此查看github commit

    三、API 使用 ABAC

    1. 上面使用的 Policy 比较简单,仅仅用到了 user claim。那么,如果需要更复杂的验证机制,比如用户编辑的图片是不是属于他,服务器当前时间是不是晚上等。

    例如下面这几种情况


    image.png

    这个时候就需要编写复杂的验证 handler 了


    image.png
    1. 新增类 MustOwnImageRequirement
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    
    namespace ImageGallery.API.Authorization
    {
        public class MustOwnImageRequirement: IAuthorizationRequirement
        {
            public MustOwnImageRequirement()
            {
            }
        }
    }
    

    新增类 MustOwnImageHandler

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using ImageGallery.API.Services;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc.Filters;
    
    namespace ImageGallery.API.Authorization
    {
        public class MustOwnImageHandler:AuthorizationHandler<MustOwnImageRequirement>
        {
            private readonly IGalleryRepository repository;
            public MustOwnImageHandler(IGalleryRepository repo)
            {
                repository = repo;
            }
    
            protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MustOwnImageRequirement requirement)
            {
                var filterContext = context.Resource as AuthorizationFilterContext;
                if (filterContext == null)
                {
                    context.Fail();
                    return Task.CompletedTask;
                }
    
                var imageId = filterContext.RouteData.Values["id"].ToString();
                if (!Guid.TryParse(imageId, out Guid imageGuid))
                {
                    context.Fail();
                    return Task.CompletedTask;
                }
    
                var ownerId = context.User.Claims.FirstOrDefault(c => c.Type == "sub").Value;
                if (!repository.IsImageOwner(imageGuid, ownerId)
                    && context.User.Claims.FirstOrDefault(c => c.Type == "role").Value != "admin")
                {
                    context.Fail();
                    return Task.CompletedTask;
                }
    
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
        }
    }
    

    Startup::ConfigureServices()添加如下代码:

                services.AddAuthorization(options =>
                {
                    options.AddPolicy(
                        "MustOwnImage",
                        policyBuilder =>
                        {
                            policyBuilder.RequireAuthenticatedUser();
                            policyBuilder.AddRequirements(new MustOwnImageRequirement());
                        });
                });
                services.AddScoped<IAuthorizationHandler, MustOwnImageHandler>();
    

    ImageController在相关接口添加属性

    [Authorize("MustOwnImage")]

    如果想要在 API 获取额外的 claims,可按照如下修改 GetApiResources

    image.png

    运行即可检验代码生效


    image.png

    点此查看 github commit

    相关文章

      网友评论

        本文标题:7-OAuth2 & OpenID Connect &a

        本文链接:https://www.haomeiwen.com/subject/sdvgiftx.html