c# - IdentityServer:具有不同授权类型的多个客户端,策略无法正常工作
问题描述
我有一个具有以下“看起来像”配置的身份服务器设置:
return new List<Client>
{
new Client
{
[...]
AllowedGrantTypes = GrantTypes.Implicit,
[....]
},
new Client
{
[...]
AllowedGrantTypes = GrantTypes.ClientCredentials,
[....]
}
};
和这样注释的控件:
[Route("api/forms")]
[ApiController]
[Authorize(Policy = "user.api.portfolio.manager")]
[Authorize(Policy = "application.api.portfolio.manager")]
public class FormsController : ControllerBase
{
[...]
}
和一个政策
private System.Action<AuthorizationOptions> AddJwtAuthorizationPolicyForRole()
{
return options => { options.AddPolicy("**POLICY_FOR_GRANT_IMPLICIT**", policy => {
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
policy.RequireClaim(ClaimTypes.Role, "USER_ACCESSIBLE");
});
};
}
private System.Action<AuthorizationOptions> AddJwtAuthorizationPolicyForRole()
{
return options => { options.AddPolicy("**POLICY_FOR_CLIENT_CREDENTIALS**", policy => {
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
};
}
所以我想实现:
使用 GrantType.ClientCredentials 的客户端无需任何进一步的需求即可访问控制器。使用隐式模式的客户端必须具有角色 USER_ACCESSIBLE
如果配置如上所示,则必须应用两种策略 -> 两种授权类型均失败。
如何使用 IdentityServer 实现所描述的行为,每个授权类型可能有一个独立的策略,以便应用?
在此先感谢您的帮助。
解决方案
最简单的解决方案是为 Implicit + ClientCredential 添加另一个单一策略来实现 OR 条件的逻辑。
或者您可以创建一个自定义属性,例如:
MultiplePolicysAuthorizeAttribute
public class MultiplePolicysAuthorizeAttribute : TypeFilterAttribute { public MultiplePolicysAuthorizeAttribute(string policys, bool isAnd = false) : base(typeof(MultiplePolicysAuthorizeFilter)) { Arguments = new object[] { policys, isAnd }; } }
MultiplePolicysAuthorizeFilter
public class MultiplePolicysAuthorizeFilter : IAsyncAuthorizationFilter { private readonly IAuthorizationService _authorization; public string Policys { get; private set; } public bool IsAnd { get; private set; } public MultiplePolicysAuthorizeFilter(string policys, bool isAnd, IAuthorizationService authorization) { Policys = policys; IsAnd = isAnd; _authorization = authorization; } public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { var policys = Policys.Split(";").ToList(); if (IsAnd) { foreach (var policy in policys) { var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy); if (!authorized.Succeeded) { context.Result = new ForbidResult(); return; } } } else { foreach (var policy in policys) { var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy); if (authorized.Succeeded) { return; } } context.Result = new ForbidResult(); return; } } }
如果操作需要匹配策略之一(或):
[MultiplePolicysAuthorize("POLICY_FOR_GRANT_IMPLICIT;POLICY_FOR_CLIENT_CREDENTIALS")]
如果操作需要匹配所有策略(和):
[MultiplePolicysAuthorize("POLICY_FOR_GRANT_IMPLICIT;POLICY_FOR_CLIENT_CREDENTIALS",true)]
推荐阅读
- python - nginx 主管 django gunicorn 404
- php - Laravel如何在控制器中获取Helper函数返回值作为url路径
- android - 如何在 Kotlin 中将数组转换为集合(HashSet)?
- sql - 多个插入与一个具有多个值的插入
- swagger - 如何在 swagger-ui 上按字母顺序显示组?
- javascript - 拆分 API 响应的日期时间
- python - 使用 pandas 数据框中的多个列的多个自定义函数聚合多个列的有效方法是什么?
- kubernetes - 从 Kubernetes 应用程序调用需要白名单 IP 的外部服务
- php - 无法访问 php 代码中的 ACF 字段
- python - 创建由两个列表构建的列表列表