IdentityServer4系列(05)【授权方式】

IdentityServer4系列(05)【授权方式】基于角色验证服务器用户 添加新的 claim newClaim JwtClaimType Role 管理员 publicclassT publicstatic TestUser Users newList TestUser newTestUser SubjectId Username alice Passwor TestUser TestUser

基于角色

验证服务器

  • 用户,添加新的claim: new Claim(JwtClaimTypes.Role, "管理员")
public class TestUsers { 
    public static List<TestUser> Users = new List<TestUser> { 
    new TestUser{ 
   SubjectId = "", 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, ""), 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 = "", 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, ""), 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"); //删除一些不需要的claim options.ClaimActions.DeleteClaim("sid"); options.ClaimActions.DeleteClaim("sub"); options.ClaimActions.DeleteClaim("idp"); //有关用户的roles options.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"); //删除一些不需要的claim options.ClaimActions.DeleteClaim("sid"); options.ClaimActions.DeleteClaim("sub"); options.ClaimActions.DeleteClaim("idp"); //有关用户的roles options.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指scope new 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()); }); }); 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232591.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux下安装tomcat并进行配置

    linux下安装tomcat并进行配置linux下安装tomcat并进行配置

    2022年5月5日
    54
  • session.setAttribute()方法

    session.setAttribute()方法session.setAttribute(“sessionName”,Object);用来设置session值的,sessionName是名称,object是你要保存的对象。session.getAttribute(“sessionName”);用来得到对应名称的session值,即得到object对象,注意需要进行类型转换!session.setAttribute(“xyyyy”,xyyy);保存session.getAttribute(“xyyyy”);取得你可以把自己要的数据什么的放在se

    2022年10月17日
    2
  • batchnorm解读

    batchnorm解读转自:https://blog.csdn.net/qq_25737169/article/details/79048516目录第一节:Batchnorm主要解决的问题1.1InternalCovariateShift1.2covariateshift第二节:Batchnorm原理解读第三节:Batchnorm源码解读第四节:Batchnorm的优…

    2022年6月3日
    44
  • 2021年全网最全最详细的SpringBoot面试题精选合集

    2021年全网最全最详细的SpringBoot面试题精选合集1.SpringBoot基础1.1什么是SpringBoot?用来简化Spring应用的初始搭建以及开发过程,使用特定的方式来进行配置 创建独立的Spring引用程序main方法运行 嵌入的tomcat无需部署war文件 简化maven配置 自动配置Spring添加对应的功能starter自动化配置>SpringBoot来简化Spring应用开发,约定大于配置,去繁化简1.2SpringBoot有哪些优点? 独立运行 SpringBoot而且内嵌了各种ser

    2022年6月7日
    79
  • php中trait的使用

    php中trait的使用

    2021年11月8日
    63
  • vue 计数器_74161计数器

    vue 计数器_74161计数器计数器的实现在页面上简单实现一个计数器<!DOCTYPEhtml><htmllang="en"><head><metach

    2022年8月7日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号