基于角色

验证服务器

  • 用户,添加新的claim: new Claim(JwtClaimTypes.Role, "管理员")
public class TestUsers{public static List<TestUser> Users = new List<TestUser>{new TestUser{SubjectId = "818727", Username = "alice", Password = "alice", Claims = {new Claim(JwtClaimTypes.Name, "Alice Smith"),new Claim(JwtClaimTypes.GivenName, "Alice"),new Claim(JwtClaimTypes.FamilyName, "Smith"),new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),new Claim(JwtClaimTypes.WebSite, "http://alice.com"),new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json),new Claim(JwtClaimTypes.Role, "管理员")}},new TestUser{SubjectId = "88421113", Username = "bob", Password = "bob", Claims = {new Claim(JwtClaimTypes.Name, "Bob Smith"),new Claim(JwtClaimTypes.GivenName, "Bob"),new Claim(JwtClaimTypes.FamilyName, "Smith"),new Claim(JwtClaimTypes.Email, "BobSmith@email.com"),new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),new Claim(JwtClaimTypes.WebSite, "http://bob.com"),new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json),new Claim("location", "somewhere"),new Claim(JwtClaimTypes.Role, "普通用户")}}};}
  • Config.cs, 添加一个IdentityResource, 添加一个scope
public static IEnumerable<IdentityResource> GetIdentityResources(){return new IdentityResource[]{new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResources.Address(),new IdentityResources.Phone(),new IdentityResources.Email(),new IdentityResource("roles","角色", new List<string>{ JwtClaimTypes.Role}) //这里的roles指scope};}new Client{ClientId = "hybrid client",ClientName = "ASP.NET Core Hybrid client",ClientSecrets= { new Secret("hybrid_secret".Sha256())},AllowedGrantTypes=GrantTypes.Hybrid,RedirectUris ={"http://localhost:7000/signin-oidc"},PostLogoutRedirectUris ={"http://localhost:7000/signout-callback-oidc"},AllowOfflineAccess = true,AlwaysIncludeUserClaimsInIdToken=true,AllowedScopes ={"api1",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile,IdentityServerConstants.StandardScopes.Address,IdentityServerConstants.StandardScopes.Email,IdentityServerConstants.StandardScopes.Phone,"roles"}}

web服务器

  • Startup.cs, 在cookies中配置授权失败的转向页,在OpenIdConnect中配置有关roles
services.AddAuthentication(options =>{options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => {options.AccessDeniedPath = "/Authorization/AccessDenied";}).AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>{options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.Authority = "http://localhost:5000";options.RequireHttpsMetadata = false;options.ClientId = "hybrid client";options.ClientSecret = "hybrid_secret";options.SaveTokens = true;options.ResponseType = "code id_token";options.Scope.Clear();options.Scope.Add("api1");options.Scope.Add(OidcConstants.StandardScopes.OpenId);options.Scope.Add(OidcConstants.StandardScopes.Profile);options.Scope.Add(OidcConstants.StandardScopes.Email);options.Scope.Add(OidcConstants.StandardScopes.Phone);options.Scope.Add(OidcConstants.StandardScopes.Address);options.Scope.Add(OidcConstants.StandardScopes.OfflineAccess);options.Scope.Add("roles");//把一些被自动过滤掉的claim找回来options.ClaimActions.Remove("nbf");options.ClaimActions.Remove("amr");options.ClaimActions.Remove("exp");//删除一些不需要的claimoptions.ClaimActions.DeleteClaim("sid");options.ClaimActions.DeleteClaim("sub");options.ClaimActions.DeleteClaim("idp");//有关用户的rolesoptions.TokenValidationParameters = new TokenValidationParameters{NameClaimType = JwtClaimTypes.Name,RoleClaimType = JwtClaimTypes.Role};});
  • 在控制器中
[Authorize(Roles = "管理员,普通用户")]

基于策略,将多个claim组合在一起

在Startup.cs中的services.AddAuthorization中配置策略

//配置策略services.AddAuthorization(options => {options.AddPolicy("SmithInSomewhere", builder => {builder.RequireAuthenticatedUser();builder.RequireClaim(JwtClaimTypes.FamilyName, "Smith"); //这里值可以有多个,逗号分隔builder.RequireClaim("location", "somewhere"); //这个不是标准claim哦});});

这里自定义的claim叫做location,位于某个scope中,这个scope需要在services.AddAuthentication中加上。

services.AddAuthentication(options =>{options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => {options.AccessDeniedPath = "/Authorization/AccessDenied";}).AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>{options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.Authority = "http://localhost:5000";options.RequireHttpsMetadata = false;options.ClientId = "hybrid client";options.ClientSecret = "hybrid_secret";options.SaveTokens = true;options.ResponseType = "code id_token";options.Scope.Clear();options.Scope.Add("api1");options.Scope.Add(OidcConstants.StandardScopes.OpenId);options.Scope.Add(OidcConstants.StandardScopes.Profile);options.Scope.Add(OidcConstants.StandardScopes.Email);options.Scope.Add(OidcConstants.StandardScopes.Phone);options.Scope.Add(OidcConstants.StandardScopes.Address);options.Scope.Add(OidcConstants.StandardScopes.OfflineAccess);options.Scope.Add("roles");options.Scope.Add("locations");//把一些被自动过滤掉的claim找回来options.ClaimActions.Remove("nbf");options.ClaimActions.Remove("amr");options.ClaimActions.Remove("exp");//删除一些不需要的claimoptions.ClaimActions.DeleteClaim("sid");options.ClaimActions.DeleteClaim("sub");options.ClaimActions.DeleteClaim("idp");//有关用户的rolesoptions.TokenValidationParameters = new TokenValidationParameters{NameClaimType = JwtClaimTypes.Name,RoleClaimType = JwtClaimTypes.Role};});

以上的locations这个scope需要在验证服务器上设置。

public static IEnumerable<IdentityResource> GetIdentityResources(){return new IdentityResource[]{new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResources.Address(),new IdentityResources.Phone(),new IdentityResources.Email(),new IdentityResource("roles","角色", new List<string>{ JwtClaimTypes.Role}), //这里的roles指scopenew IdentityResource("locations","地点", new List<string>{ "location"} )};}
new Client{ClientId = "hybrid client",ClientName = "ASP.NET Core Hybrid client",ClientSecrets= { new Secret("hybrid_secret".Sha256())},AllowedGrantTypes=GrantTypes.Hybrid,RedirectUris ={"http://localhost:7000/signin-oidc"},PostLogoutRedirectUris ={"http://localhost:7000/signout-callback-oidc"},AllowOfflineAccess = true,AlwaysIncludeUserClaimsInIdToken=true,AllowedScopes ={"api1",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile,IdentityServerConstants.StandardScopes.Address,IdentityServerConstants.StandardScopes.Email,IdentityServerConstants.StandardScopes.Phone,"roles","locations"}}

更复杂的策略

  • 一个action可以有多个Policy作用
  • 一个Policy, 通过RequireAuthenticatedUser,RequireClaim, IAuthorizationRequirement生成,
  • 一个IAuthorizationRequirement中有多个AuthorizationHandler

首先需要实现IAuthorizationRequirement

public class SmithInSomewhereRequirement : IAuthorizationRequirement{public SmithInSomewhereRequirement(){}}

其次需要一个AuthorizationHandler

    public class SmithInSomewhereHandler : AuthorizationHandler<SmithInSomewhereRequirement>{protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SmithInSomewhereRequirement requirement){//var filterContext = context.Resource as AuthorizationFilterContext;//if(filterContext==null)//{//    context.Fail();//    return Task.CompletedTask;//}var familyName = context.User.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.FamilyName)?.Value;var location = context.User.Claims.FirstOrDefault(t => t.Type == "location")?.Value;if(familyName == "Smith" && location == "somewhere" && context.User.Identity.IsAuthenticated){context.Succeed(requirement);return Task.CompletedTask;}context.Fail();return Task.CompletedTask;}}

最后在startup.cs中设置:

//配置策略
services.AddAuthorization(options => {//options.AddPolicy("SmithInSomewhere", builder => {//    builder.RequireAuthenticatedUser();//    builder.RequireClaim(JwtClaimTypes.FamilyName, "Smith"); //这里值可以有多个,逗号分隔//    builder.RequireClaim("location", "somewhere"); //这个不是标准claim哦//});options.AddPolicy("SmithInSomewhere", builder => {builder.AddRequirements(new SmithInSomewhereRequirement());});
});

IdentityServer4系列(05)【授权方式】相关推荐

  1. IdentityServer4系列 | 资源密码凭证模式

    一.前言 从上一篇关于客户端凭证模式中,我们通过创建一个认证授权访问服务,定义一个API和要访问它的客户端,客户端通过IdentityServer上请求访问令牌,并使用它来控制访问API.其中,我们也 ...

  2. IdentityServer4系列 | 快速搭建简易项目

    一 .前言 从上一篇关于 常见术语说明中,主要是对「IdentityServer4」的说明,以及其中涉及常见的术语的表述说明,包括对身份认证服务器.用户.客户端.资源以及各个令牌等进行对比区别说明. ...

  3. 基于.NetCore3.1搭建项目系列 —— 认证授权方案之Swagger加锁

    1 开始 在之前的使用Swagger做Api文档中,我们已经使用Swagger进行开发接口文档,以及更加方便的使用.这一转换,让更多的接口可以以通俗易懂的方式展现给开发人员.而在后续的内容中,为了对a ...

  4. 基于.NetCore3.1系列 —— 认证授权方案之授权揭秘 (下篇)

    一.前言 回顾:基于.NetCore3.1系列 -- 认证授权方案之授权揭秘 (上篇) 在上一篇中,主要讲解了授权在配置方面的源码,从添加授权配置开始,我们引入了需要的授权配置选项,而不同的授权要求构 ...

  5. 【.NET Core项目实战-统一认证平台】第十四章 授权篇-自定义授权方式

    上篇文章我介绍了如何强制令牌过期的实现,相信大家对IdentityServer4的验证流程有了更深的了解,本篇我将介绍如何使用自定义的授权方式集成老的业务系统验证,然后根据不同的客户端使用不同的认证方 ...

  6. oauth2.0 php简化模式,OAuth2.0学习(1-5)授权方式2-简化模式(implicit grant type)

    授权方式2-简化模式(implicit grant type) 简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授 ...

  7. OAuth 2.0 - Authorization Code授权方式详解

    I:OAuth 2.0 开发前期准备 天上不会自然掉馅饼让你轻松地去访问到人家资源服务器里面的用户数据资源,所以你需要做的前期开发准备工作就是把AppKey, AppSecret取到手 新浪获取传送门 ...

  8. 数据可视化系列-05数据分析报告

    文章目录 数据可视化系列-05数据分析报告 1.了解初识数据分析报告 数据分析报告简介 数据分析报告的作用 报告的能力体现 报告编写的原则 报告种类 2.掌握数据分析报告结构 标题页 目录 前言 正文 ...

  9. 微软授权方式连载二:Windows XP版本类型及授权方式

    一.FPP版 FPP (Full Packaged Product)就是零售版,具体还分两种:完全零售版可以全新安装,也可以升级安装:升级版只做升级安装.这种版本的Windows XP产品有精美的包装 ...

最新文章

  1. 福师计算机导论在线作业一,福师《计算机导论》在线作业一..doc
  2. html语言难不难学,Web前端开发难学吗?
  3. linux 内核网络协议栈--linux内核路由机制(一)
  4. CVPR 2020 《Where Does It Exist: Spatio-Temporal Video Grounding for Multi-Form Sentences》论文笔记
  5. Android插件化开发之运行未安装apk的activity
  6. 8月9日发布!华为EMUI 10将在华为开发者大会上登场
  7. fstream的用法-----------------2012.12.26
  8. 以太坊POA共识机制Clique源码分析
  9. JavaSE基础——代码块、继承、方法重写和final关键字
  10. mysql计算3000分钟后的日期_MySQL – 计算两个日期时间之间的净时差,同时排除中断?...
  11. 最新《北风网Python零基础人工智能就业教程》
  12. win7下开启梦幻桌面
  13. ps扁平图之 油画(莫奈)中的色彩与几何
  14. Android判断手机是否是小米MIUI系统
  15. python算法习题(一): 排列组合
  16. MeanTeacher文章解读+算法流程+核心代码详解
  17. 爬虫工程师想拿更高薪,这点不要忽略
  18. 麦语言通达信公式唐安奇交易通道改写转换成python
  19. 教你如何提高微信公众号粉丝粘度
  20. vyos下goahead的编译后移植

热门文章

  1. 彩色空间(Color Space)
  2. 赶集网否认倒闭:是不是好公司,两三年后见分晓
  3. Linux系统管理上机作业2
  4. [Pandas] 分组比例计算求和
  5. 跨考没有计算机二级,计算机二级可以跨学校报名吗 计算机二级可以跨校报考吗?...
  6. 2021-06-29凯云软件测试项目管理系统系统描述
  7. C++ 百钱百鸡问题
  8. java 设置纸张大小设置_java 用itext设置pdf纸张大小操作
  9. 【微服务】配置了端口号却还是在 8080端口启动的原因
  10. 大数据面试题(一)----HADOOP 面试题