5-OAuth2 & OpenID Connect & Asp net core 使用 Claims

一、尝试获取 Claim 研究

  1. 之前获取到的 Claims


    5-OAuth2 & OpenID Connect & Asp net core 使用 Claims_第1张图片
    image.png

    在 Client 端的 Startup 构造函数添加代码:

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            // 清除默认的 Claim Maper
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        }

再运行看输出:

Identity token:eyJhbGciOiJSUzI1NiIsImtpZCI6ImM5ODExYjU4NDg5Yzk4Y2RlOTNlYWM2NmJmMjVhNzUzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MzM0NjYwODcsImV4cCI6MTUzMzQ2NjM4NywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMTkiLCJhdWQiOiJqdW5ndW9ndW9pbWFnZWdhbGxlcnljbGllbnQiLCJub25jZSI6IjYzNjY5MDYyODc5MTI0ODAyNC5OV0U1TkRrMU4yRXROVGMxTnkwMFlXWXpMVGxrTnpRdE1EaGhZemxrWW1WbE1XRTBOelptWWpCbVpUSXRZelJpWkMwME9Ea3pMV0kxWXpndE9UTTJPV1EyTldJNU1HVmgiLCJpYXQiOjE1MzM0NjYwODcsImF0X2hhc2giOiJtek1wNXM4dXdsMkdSTU1GTnN4bmV3Iiwic2lkIjoiMjYxN2JjZTBjZTkxOTJhOTZiYzhlZTdlZTU0ZmRmMzMiLCJzdWIiOiJiNzUzOTY5NC05N2U3LTRkZmUtODRkYS1iNDI1NmUxZmY1YzciLCJhdXRoX3RpbWUiOjE1MzM0NjYwODMsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.DN52cfSDP4NNkP9r97bZJ66A_W9IiQLcf8hLLl7w9xbKE7HDNgD7aM36nHckxQ3gYi87p2aaMhUQ7xEth9K9e-Fu_KbdLQ9BUgSA3LrCqbEP2aiHcw6tqnhu85Ic15rDO5z926VLYOFNGE8ukbojZT9uwmJsPLLrrY4jO_I7mp_uUF4P4qoCXZ9IOaIHsHtTciYBW1O4D5uqU91osyRSOuQKwaT4DJy87dmAX-Xg7oN_9qKl227dZxaJ6ickkKCcjn5uSQzP2Zej3XvM8k2Q149Pn4uWabCyVXWDO8oouZkI4SQMu7jbGrZsJ6-TxBujjpB844DOo-f3pAbPn0FiwQ
Claim type : sid - Claim value : 2617bce0ce9192a96bc8ee7ee54fdf33
Claim type : sub - Claim value : b7539694-97e7-4dfe-84da-b4256e1ff5c7
Claim type : idp - Claim value : local
Claim type : name - Claim value : Frank Hawk
Claim type : given_name - Claim value : Frank
Claim type : family_name - Claim value : Hawk

发现没有了以前的 amr,编辑 ConfigureServices 中的 AddOpenIdConnect, 添加代码

                    // 从 filter 中移除 amr, 代表需要 get 【amr】 的值
                    options.ClaimActions.Remove("amr");
                    // 不需要 sid 和 idp 的值
                    options.ClaimActions.DeleteClaim("sid");
                    options.ClaimActions.DeleteClaim("idp");

在运行

Identity token:eyJhbGciOiJSUzI1NiIsImtpZCI6ImM5ODExYjU4NDg5Yzk4Y2RlOTNlYWM2NmJmMjVhNzUzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MzM0NjY1NzMsImV4cCI6MTUzMzQ2Njg3MywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMTkiLCJhdWQiOiJqdW5ndW9ndW9pbWFnZWdhbGxlcnljbGllbnQiLCJub25jZSI6IjYzNjY5MDYzMjc4MTMyMzA2Ny5OREk1TjJVeVlUY3RNVFJrTnkwMFpXTTJMVGhsTkdJdFlqVTBaVEU0Tm1VNU56TTVOekk1WVRJeE16UXRZbVF3TXkwME5HTXpMVGxpT0RFdFkyRXhaamd5TmpabU5HTTAiLCJpYXQiOjE1MzM0NjY1NzMsImF0X2hhc2giOiJpWUZ6aXhKSmxyNUl5cWlCbDJlYmhBIiwic2lkIjoiNzlhZTkxNzE1MTVjMDg4MTJjNmFmN2RiOGE4ODVlN2UiLCJzdWIiOiJiNzUzOTY5NC05N2U3LTRkZmUtODRkYS1iNDI1NmUxZmY1YzciLCJhdXRoX3RpbWUiOjE1MzM0NjY1NTksImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.kO-J-KNCltyMwKLNu-rJEx2ZDwSmexKEYFP4kG43ZSqLTdjqw13viIEWP42TnDfAaE341K7pzUYLPQJ0jB8jRwaLsrXo_Mab25Zt-KaVUGts3xCWq4pfqeKZv1w59OnHg2bRdWdNKtfXwJMG9D2H3dCd-a9gYH786W9F43kepw2smHWXPjoOW3o-bI5rHbV0o5tAfjdsrKsTIk26rnGB11zq3K_AG6lCZyycsKbi1lBDJw7-LuvY49vdaN-IEsC04ST7RdFL-BYNVHbg-ifXpN3gFx_qvWV8ku25UratTS5zyKZSgfQ4oI2IPSiMSEEzQOl0eHuTvK9znsDJ2G0H8A
Claim type : sub - Claim value : b7539694-97e7-4dfe-84da-b4256e1ff5c7
Claim type : amr - Claim value : pwd
Claim type : name - Claim value : Frank Hawk
Claim type : given_name - Claim value : Frank
Claim type : family_name - Claim value : Hawk

可以看到 amr 又回来了,而且 idpsid 被移除

  1. 查看 asp net core OpenIdConnecOptions源代码
    5-OAuth2 & OpenID Connect & Asp net core 使用 Claims_第2张图片
    image.png

    默认只有这几种 Claim mapping, 所以即使 options.ClaimActions.Remove("address"); 也无法生效,因为本身没有 mapping
    ,那么,我们仿照添加如下代码 options.ClaimActions.MapUniqueJsonKey("address", "address");, 再运行查看,得到了 address 的值
Claim type : sub - Claim value : b7539694-97e7-4dfe-84da-b4256e1ff5c7
Claim type : amr - Claim value : pwd
Claim type : name - Claim value : Frank Hawk
Claim type : given_name - Claim value : Frank
Claim type : family_name - Claim value : Hawk
Claim type : profile - Claim value : https://frank.com
Claim type : address - Claim value : USA. LA

二、手动获取 UserInfo-----新增一个订购实体图画的页面,在页面中显示登录用户的地址

  1. 新增一个Model类OrderFrameViewModel
    public class OrderFrameViewModel
    {
        public string Address { get; private set; } = string.Empty;

        public OrderFrameViewModel(string address)
        {
            Address = address;
        }
    }
  1. 新建页面
    Views -> Gallery 新增 View : OrderFrame 仅用来显示 ViewModel 中的地址
@model ImageGallery.Client.ViewModels.OrderFrameViewModel

选择一张你喜欢的图片,定做一个实体画
系统记录您的地址为:
@Model.Address
如果这个地址不正确,请联系我们。
  1. 修改 _Layout.cshtml 添加导航

  • 订购实体版图画
    1. 接下来编写 Controller 里面的 action【另一种手动获取 address 的方法】
    • nuget package 安装 IdentityModel
      image.png
            public async Task OrderFrame()
            {
                // 获取 UserInfoEndpoint
                var discoveryClient = new DiscoveryClient("https://localhost:44319");
                var metaDataResponse = await discoveryClient.GetAsync();
    
                var userInfoClient = new UserInfoClient(metaDataResponse.UserInfoEndpoint);
    
                // 获取 AccessToken
                var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
    
                // 获取 UserInfo
                var response = await userInfoClient.GetAsync(accessToken);
                if (response.IsError)
                {
                    throw  new Exception("Problem accesing the UserInfo endpoint");
                }
    
                var address = response.Claims.FirstOrDefault(c => c.Type == "address")?.Value;
                return View(new OrderFrameViewModel(address));
            }
    

    运行,点击 OrderFrame 页,地址成功显示


    5-OAuth2 & OpenID Connect & Asp net core 使用 Claims_第3张图片
    image.png

    三、新增 ClaimType

    1. 修改 IDP Config 类
    • GetIdentityResources() 返回新增两个

    new IdentityResource("guoguoextrainfo", "Guo's extra memo", new List(){"extra"}),
    new IdentityResource("roles", "Your role(s)", new List(){"role"})

    • 在 GetClients() 中把scope添加进去

    AllowedScopes =
    {
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Profile,
    IdentityServerConstants.StandardScopes.Address,
    "roles",
    "guoguoextrainfo"
    }

    • GetUsers() 里面给 user 赋相应的值

    new Claim("role","admin"),
    new Claim("extra","俊果果是网站管理员")

    1. 修改 Client 的 Starup 类
    • ConfigureServices::AddAuthentication 添加代码

    options.Scope.Add("roles");
    options.Scope.Add("guoguoextrainfo");
    options.ClaimActions.MapUniqueJsonKey("role", "role");
    options.ClaimActions.MapUniqueJsonKey("extra", "extra");

    1. 运行
    • 登录后的授权界面


      5-OAuth2 & OpenID Connect & Asp net core 使用 Claims_第4张图片
      image.png
    • 输出日志
    Identity token:eyJhbGciOiJSUzI1NiIsImtpZCI6ImM5ODExYjU4NDg5Yzk4Y2RlOTNlYWM2NmJmMjVhNzUzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MzM0NzIyMTgsImV4cCI6MTUzMzQ3MjUxOCwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMTkiLCJhdWQiOiJqdW5ndW9ndW9pbWFnZWdhbGxlcnljbGllbnQiLCJub25jZSI6IjYzNjY5MDY4NTY0OTA0NjAwNC5aamsyTWpSallUTXRNREJqTkMwME5EQTNMV0V4WmpVdE9HRXpNelE1T1RVM1ltSTROek14WkRCbU4yRXRNemsxTVMwME1XSXpMVGxpWmpNdE0yWmlZamt4TnpZM01UZGoiLCJpYXQiOjE1MzM0NzIyMTgsImF0X2hhc2giOiJnT1pJMl8zR2h4TWpiRUxHTUdPbXlRIiwic2lkIjoiNWFhODBkYWE1NzBlNWFkODk5NjlmODAyOWNhZjY5YWEiLCJzdWIiOiJiNzUzOTY5NC05N2U3LTRkZmUtODRkYS1iNDI1NmUxZmY1YzciLCJhdXRoX3RpbWUiOjE1MzM0NzE4MDMsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.tpBYUSM16EDUNKT4XHcUqWgFkkX8DnNc9RlGqVf2Tkg70fdHfSuNgukhhuEK2vCusdIyE9ovtQwCHhrjNoqg2t1Xa9fFmNdcKY2JeDsS_1_dQCUQzvAWCXiRwNiRNeeer6bgMkJWCMat5ERclUthiM5t3d6mipMZDXuUioMZsxnhSeHk21_Eod8qme-yeakEFYGwzKOf19LBsJtVkfBDWc1pgIH86h2TjRBCbNXL96W1QUUq_RS1GvCfo4GY-WqKlvzLebKs9TcISDnoYXt6PmVYvQPw7gbTeMW91XxPWrqJgiKvVnY7wnPRxxfZDqvNa3-mnh15Z4GeVZgyPole9w
    Claim type : sub - Claim value : b7539694-97e7-4dfe-84da-b4256e1ff5c7
    Claim type : amr - Claim value : pwd
    Claim type : name - Claim value : Frank Hawk
    Claim type : given_name - Claim value : Frank
    Claim type : family_name - Claim value : Hawk
    Claim type : profile - Claim value : https://frank.com
    Claim type : address - Claim value : USA. LA
    Claim type : role - Claim value : FreeUser
    Claim type : extra - Claim value : Frank 才14岁就上大学了,厉害
    

    信息全部取出!

    四、利用 role claim 确定权限

    1. 修改 OderFrame
    • 修改 OrderFrameViewModel, 添加属性

    public string ExtraInfo { get; set; }
    public string Role { get; set; }

    • 修改 OrderFrame.cshtml

    @if (@Model.Role == "FreeUser")
    {

    您还不是付费用户哦,请先成为会员吧!

    }
    else
    {
    系统已记录请求,货品将择日发出!

    }

    • 修改 Controller::OrderFrame方法
                // 获取 Model
                var model = new OrderFrameViewModel(User.Claims.FirstOrDefault(c => c.Type == "address")?.Value);
                model.ExtraInfo = User.Claims.FirstOrDefault(c => c.Type == "extra")?.Value;
                model.Role = User.Claims.FirstOrDefault(c => c.Type == "role")?.Value;
                // 传入 View
               return View(model);
    

    再次运行,以不同角色的人登录,会显示不同的界面

    1. 新增 admin page, 管理员可用
    • 修改 _Layout页面, nav bar 新增按钮
                        @if (User.IsInRole("admin"))
                        {
                            
  • 管理网站
  • }
    • 为该按钮新增的 action 添加 View 和 Controller 处理逻辑
    • 修改 Startup的配置,添加
                        options.TokenValidationParameters = new TokenValidationParameters()
                        {
                            NameClaimType = JwtClaimTypes.GivenName,
                            RoleClaimType = "role" 
                        };
    

    运行后,只有配置的 role 为 admin 的用户登录时才能看到 按钮
    但是,非管理员也可以登陆后直接复制该页面的链接访问进去
    要避免这个问题, 将 ManageSite 打上如下所示属性标记

            [Authorize(Roles = "admin,administrator")]
            public async Task ManageSite()
            {
                return View();
            }
    

    再用无权限账户 copy 管理页面得到提示

    5-OAuth2 & OpenID Connect & Asp net core 使用 Claims_第5张图片
    image.png

    发现被自动重定向到了 AccountControllerAccessDenied action

    五、实现一个 AuthorizationController

    1. 新增 Controller
        public class AuthorizationController : Controller
        {
            public IActionResult AccessDenied()
            {
                return View();
            }
        }
    
    1. 新增 View
    @{
        ViewBag.Title = "访问受限";
    }
    
    

    您当前无权访问此页面

    1. StarupConfigureServices 中将该网址配置到Cookie中
      5-OAuth2 & OpenID Connect & Asp net core 使用 Claims_第6张图片
      image.png

    完成后运行,会发现权限提示页面更新了


    5-OAuth2 & OpenID Connect & Asp net core 使用 Claims_第7张图片
    image.png

    github 代码地址:Claims 的使用

    你可能感兴趣的:(5-OAuth2 & OpenID Connect & Asp net core 使用 Claims)