主要目标是当OIDC用户拥有类型为“ BlockedFrom”的自定义声明时阻止访问门户,该声明已添加在ClaimsTransformation中。
我已经通过Startup.Configure
方法的中间件解决了它。一般原因是保留原始请求URL,而不重定向到/ Account / AccessDenied页面。
app.Use((context, next) =>
{
var user = context.User;
if (user.IsAuthenticated())
{
// Do not rewrite path when it marked with custom [AllowBlockedAttribute]!
// /Home/Logout, for example. But how?
//
if (user.HasClaim(x => x.Type == UserClaimTypes.BlockedFrom))
{
// Rewrite to run specific method of HomeController for blocked users
// with detailed message.
//
context.Request.Path = GenericPaths.Blocked;
}
}
return next();
});
但是有一个意外结果:Logout
的{{1}}方法也被阻止了。用户被阻止时无法注销,哈哈!
首先想到的是-检查自定义属性,例如HomeController
。中间件中的硬编码路径常量看起来很疯狂。如何在中间件中访问调用方法的属性?
另一种(也是更优雅的)方法是将此逻辑放到自定义[AllowBlockedAttribute]
中,并在BlockedHandler : AuthorizationHandler<BlockedRequirement>
方法的MVC选项中将其分配为常规策略:
Startup.ConfigureServices
services.AddSingleton<IAuthorizationHandler, BlockedHandler>();
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddRequirements(new BlockedRequirement())
.Build();
// Set the default authentication policy to require users to be authenticated.
//
options.Filters.Add(new AuthorizeFilter(policy));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
的假设实现:
BlockedHandler
好的,现在我们可以处理自定义属性了。似乎AuthorizationHandler并不是告诉HttpContext无需重定向即可更改其RequestPath的最佳位置。在哪里可以做到?
答案 0 :(得分:1)
我已经在框架源代码中进行了一些挖掘,并找到了一种以授权处理程序方式进行这项工作的方法。
授权过程的入口点是 AuthorizeFilter 。筛选器上下文具有 Result 属性,该属性接受 IActionResult 。通过设置此属性,您可以缩短请求并显示所需的任何操作结果(包括视图)。这是解决方案的关键。
如果遵循执行路径,您将意识到筛选器上下文将传递到授权组件,并且可以在 IAuthorizationHandler.HandleRequirementAsync 方法中使用。您可以通过向下转换(如OP所示)从上下文对象的 Resource 属性中获取它。
还有一件重要的事情:您必须从授权处理程序中返回成功,否则不可避免地将导致重定向。 (如果您签出default implementation of IPolicyEvaluator,这一点将变得很清楚。)
因此,将所有这些放在一起:
open
答案 1 :(得分:0)
我认为AuthorizationHandler绝对是放置此逻辑的更好位置。但是-如果我正确理解-您的问题是,在此处理程序执行时,已经选择了要调用的动作,因此您无法再更改路由。
当然,标准方法是启动重定向,但您要避免这种情况以保留当前URL。
鉴于上述情况,我可以想到一种方法:全局action filter。
动作过滤器可以在调用单个动作方法之前和之后立即运行代码。它们可用于处理传递给操作的参数以及从操作返回的结果。
OnActionExecuting 方法似乎是放置逻辑的正确位置,因为此时您可以访问action方法的属性,并且有机会缩短处理过程(通过设置(如果用户被阻止,则 ActionExecutingContext 参数的 Result 属性)。
如果您不熟悉过滤器的概念,则可以在this MSDN article中找到所有详细信息。