IdentityServer4 QuckStart 授权与自定义Claims
最近在折腾IdentityServer4,为了简单,直接使用了官方给的QuickStart示例项目作为基础进行搭建。有一说一,为了保护一个API,感觉花费的时间比写一个API还要多。
本文基于ASP.NET CORE 3.1, IdentityServer4 3.1.3。代码皆为关键代码,贴全了太多了。
好不容易跑起来了,最终的任务要落实到授权的工作上来。在API中使用Authorize用来限制用户的访问。
[Route("api/[controller]")]
[Authorize(Roles = "Administrator")]
[ApiController]
public class UserInfoController : ControllerBase
{
/// <summary>
/// 无参GET请求
/// </summary>
/// <returns></returns>
[HttpGet()]
[ProducesResponseType(typeof(ReturnData<IEnumerable<UserInfo>>), Status200OK)]
public async Task<ActionResult> Get()
{
var info = new Info<UserInfo>();
return Ok(new ReturnData<IEnumerable<UserInfo>>(await info.Get()));
}
然而在使用的时候,虽然正确取得授权,但是却无法正常访问API,一直提示401没有授权错误。仔细检查,发现IdentityServer4返回的内容并没有返回role的JwtClaimTypes,没有它,Authorize无法正常工作。
{
"nbf": 1587301921,
"exp": 1587305521,
"iss": "http://localhost:5000",
"aud": "MonitoringSystemApi",
"client_id": "webClient",
"sub": "c6c18d4d-c28e-4de5-86dd-779121216204",
"auth_time": 1587301921,
"idp": "local",
"scope": [
"roles",
"MonitoringSystemApi",
"offline_access"
],
"amr": [
"pwd"
]
}
实现
查看Config.cs,IdentityServer4默认只返回两种IdentityResource:openid和profile。按照官方的说法,这个东西定义的内容会返回到用户的token。参考。那么就果断给它安排。
public static IEnumerable<IdentityResource> Ids =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource ("roles", new List<string> { JwtClaimTypes.Role }){ Required = true}
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "webClient",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowOfflineAccess = true,
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
// scopes that client has access to
AllowedScopes = {
"roles",
"MonitoringSystemApi" }
},
执行之前,需要确保数据库中的用户数据,已经包含role的Claim。
//添加用户代码
bob = new ApplicationUser
{
UserName = "bob"
};
var result = userMgr.CreateAsync(bob, "Pass123$").Result;
if (!result.Succeeded)
{
throw new Exception(result.Errors.First().Description);
}
result = userMgr.AddClaimsAsync(bob, new Claim[]{
new Claim(JwtClaimTypes.Role, "Administrator"),
new Claim(JwtClaimTypes.Name, "Bob Smith"),
运行程序,返回值依旧没有任何变化,很挫败,只能继续折腾。
有研究通过实现IProfileService达到自定义Cliams。文章写的很详细,我这就不重复了,我实际试验过,可以成功。
但是文章末尾的注意,很重要。
“那么, 通过profileservice颁发的claims, 任意clients都能拿到”
说明这个优先级是非常高的,可以覆盖所有的行为,当然我们可以在IProfileService的实现上对权限进行进一步的设置,不过还是挺麻烦的。参考实现,参考官方
作为懒人,必然不想再费劲去折腾权限的问题,那么是否有简单点的办法呢?
网上有一些问答说到了可以通过设置Scopes来达到目的。不过过于久远,IdentityServer4已经没有这个独立的类了,说是已经被ApiResource取代了。
直觉上这个东西应该是指示要保护的API的相关内容的,好像和这个没啥关系,不过也只能死马当活马医了。修改config.cs,最终如下内容:
public static IEnumerable<ApiResource> Apis =>
new List<ApiResource>
{
new ApiResource("pls", new[]{ "role"}),
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "webClient",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowOfflineAccess = true,
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
// scopes that client has access to
AllowedScopes = {
"pls"
}
},
返回结果如下:
{
"nbf": 1587301799,
"exp": 1587305399,
"iss": "http://localhost:5000",
"aud": "pls",
"client_id": "webClient",
"sub": "c6c18d4d-c28e-4de5-86dd-779121216204",
"auth_time": 1587301799,
"idp": "local",
"role": "Administrator",
"scope": [
"pls",
"offline_access"
],
"amr": [
"pwd"
]
}
终于看见心心念念的自定义Claim(role),可以去访问API了。
注意,在Client中也有个Claims,添加了role并且设置
AlwaysSendClientClaims和AlwaysIncludeUserClaimsInIdToken之后,会在token中添加client_roie字段,这个是没办法用与授权的,可以理解为IdentityServer4直接指定了Client角色,并不是Identity中的角色概念。
后记
回过头来仔细看官方的文档,ApiResource中的UserClaims就是用来干这个的,折腾了半天,不如当时仔细看看文档了。
IdentityServer4 QuckStart 授权与自定义Claims的更多相关文章
- IdentityServer4客户端如何获取自定义声明,了解一下?
前言 久违了各位,之前录制过IdentityServer4的基础视频(https://space.bilibili.com/319652230/#/),有兴趣了解的童鞋可以看一下,只不过未发表成博客. ...
- 【.NET Core项目实战-统一认证平台】第十四章 授权篇-自定义授权方式
[.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何强制令牌过期的实现,相信大家对IdentityServer4的验证流程有了更深的了解,本篇我将介绍如何使用自定义的授权方 ...
- .net core Identity集成IdentityServer(2) 实现IprofileService接口在accesstoken中增加自定义claims
导读 1. 如何添加自定义的claims. 前请提要 目前我们拥有了三个web应用. localhost:40010, 验证服务器 localhost:40011, mvc客户端, 充当webapp请 ...
- Asp.net Core 系列之--5.认证、授权与自定义权限的实现
ChuanGoing 2019-11-24 asp.net core系列已经来到了第五篇,通过之前的基础介绍,我们了解了事件订阅/发布的eventbus整个流程,初探dapper ORM实现,并且简单 ...
- IdentityServer4 (3) 授权码模式(Authorization Code)
写在前面 1.源码(.Net Core 2.2) git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git 2.相关章节 2.1. ...
- 一看就懂的IdentityServer4认证授权设计方案
查阅了大多数相关资料,总结设计一个IdentityServer4认证授权方案,我们先看理论,后设计方案. 1.快速理解认证授权 我们先看一下网站发起QQ认证授权,授权通过后获取用户头像,昵称的流程. ...
- spring security 授权方式(自定义)及源码跟踪
spring security 授权方式(自定义)及源码跟踪 这节我们来看看spring security的几种授权方式,及简要的源码跟踪.在初步接触spring security时,为了实现它的 ...
- 认证授权:IdentityServer4 - 各种授权模式应用
前言: 前面介绍了IdentityServer4 的简单应用,本篇将继续讲解IdentityServer4 的各种授权模式使用示例 授权模式: 环境准备 a)调整项目结构如下: b)调整cz.Id ...
- IdentityServer4系列 | 授权码模式
一.前言 在上一篇关于简化模式中,通过客户端以浏览器的形式请求IdentityServer服务获取访问令牌,从而请求获取受保护的资源,但由于token携带在url中,安全性方面不能保证.因此,我们可以 ...
随机推荐
- vscode回车补全代码
VsCode设置回车补全代码而不换行 有一部分人不习惯用tab键补全代码,我就是其中之一,习惯了回车补全的我决定设置一波,网上找了很多, 没找到比较详细的,所以自己写一个 有一个叫keybinding ...
- 全国职业技能大赛信息安全管理与评估-MySQL弱口令利用
MySQL读文件 #coding=utf-8 import MySQLdb host = '172.16.1.' for i in range(129,131): tag = host+str(i) ...
- C 2012年笔试题
1指出程序段中的错误:分析错误的原因,并进行修改 1.1函数 swap 将两个字符串(字符数组作实参,长度不超过 100)的内容进行交换 void swap(char *pa,char *pb) { ...
- 浅谈VUE,使用watch方法监听父组件传到子组件的数据。
props:['updateData'], data(){ return{ form: { _name:'', }, } }, 第一步接收数据: props:['updateData'] 第二步动 ...
- Python-类的特性
------------恢复内容开始------------ 类及类的定义 Cat类 类的特殊方法-构造函数.析构函数 class Cat: # 构造函数 def __init__(self, nam ...
- SpringBoot 集成ehcache
1, 项目实在springboot 集成mybatis 的基础上的: https://www.cnblogs.com/pickKnow/p/11189729.html 2,pom 如下,有的不需要加, ...
- 使用SpringCloud将单体迁移至微服务
使用SpringBoot构建单体项目有一段时间了,准备对一个老项目重构时引入SpringCloud微服务,以此奠定后台服务能够应对未知的业务需求. 现在SOA架构下的服务管理面临很多挑战,比如面临一个 ...
- mongodb的增加和删除
一 mongodb中使用insert()方法来增加集合中的文档: db.myTable.insert({name:'arvin',age:12}) //对名为myTable的集合插入数据 插入数据 ...
- linux部署win服务 dotnet mono jexus
.Net Core (dotnet C#应用) dotnet 可以用在linux上运行 C#应用 适用于 SSO 统一身份认证系统 # 安装依赖 yum install libunwind yum i ...
- NCEP CFSR数据读取
一. NCEP CFSR再分析数据,时间分辨率是1小时. 1.整体读取数据情况 clear all setup_nctoolbox tic %% 读取数据文件 wind= ncgeodataset(' ...