[英]Asp.Net Boilerplate .Net Core 2.0 AbpAuthorizationFilter - ChallengeResult / Unauthorized
我正在运行带有Asp.Net Boilerplate 3.4.0 版Web 应用程序的Asp.Net Core 2.0 。
当我有一个经过身份验证的用户没有访问资源所需的权限时, AbpAuthorizationFilter
通过Abp框架设置ChallengeResult
。 此行为会导致用户返回到默认登录页面。 如果用户通过身份验证,我想设置一个ForbidResult
并将它们重定向到默认的 AccessDenied 页面。
查看我的选项后,我发现我有以下选项:
AddAbp()
服务配置之前注册MvcOptions
。 过滤器将有条件地将结果设置为“挑战”或“禁止”OnRedirectToLogin
事件(即为经过身份验证的用户自定义)HandleChallengeAsync
处理程序(即,检查请求是否经过身份验证,并为未经身份验证的请求发出 ForbidResult 或 ChallengeResult) 我注意到在 ABP 的 .Net 框架版本中,在AbpMvcAuthorizeFilter
(即HandleUnauthorizedRequest
)中有可AbpMvcAuthorizeFilter
方法; 但是,这不适用于 .Net Core 版本。 请参阅 GitHub 问题 1256 -> 使 AbpMvcAuthorizeFilter 和 AbpApiAuthorizeFilter 可覆盖
是否还有其他人需要更改为未经授权的请求返回ChallengeResult
的默认Abp行为? 如果是,您使用了什么解决方案? 我是否在Abp配置或 Asp.Net Core(除了上面列出的三个选项之外)中遗漏了一些可以让我更好地控制这种行为的东西?
如果我采用了一种解决方法,感觉就像控制这种行为的黑客一样。
在我列出的三个选项中,选项一似乎是处理此逻辑的最干净、最合适的地方。 它也不漂亮,因为我将复制整个AbpAuthorizationFilter
以仅更改几行代码。
当前代码:
context.Result = new ChallengeResult();
提议的改变:
if (context.HttpContext.User.Identity.IsAuthenticated)
{
//User is already logged in.. No need to redirect to the
//login page
context.Result = new ForbidResult();
}
else
{
context.Result = new ChallengeResult();
}
完整代码如下:
AbpAuthorizationFilter.cs请参阅 Catch 块行 - 58 - 77
选项二感觉很笨拙,因为我将引入OnRedirectToLogin
事件的逻辑必须假设经过身份验证的用户已尝试访问未经授权的资源。 目前,我只看到CookieAuthenticationHandler
通过HandleChallengeAsync
方法在Events.RedirectToLogin
中引发。 话虽如此,可以安全地假设此事件只会由ChallengeResult
结果引发。 CookieAuthenticationHandler.cs
选项三将是最后一个选项(即不惜一切代价避免)
主要目标是为尝试访问未授权资源的经过身份验证的用户提供更好的体验。 与其将用户重定向到登录页面,不如将用户重定向到未授权/禁止的页面,该页面清楚地表明他们未经授权。 这可能包括提示用户提供更高特权凭据的选项。 通过提示用户,它闻起来像一个ChallengeResult
结果流,所以也许我只是回答了我自己的问题。 对于当前的行为,我没有太多关于“为什么”发布ChallengeResult
上下文信息。 我会知道用户已登录并且引发了OnRedirectToLogin
事件。 这可能足以为经过身份验证的用户自定义ChallengeResult
的行为。 这开始感觉这是正确的解决方案。 关于使用这种方法的任何建议或反馈?
在这三个选项中,我选择了第二个选项(覆盖OnRedirectToLogin
事件),原因如下:
OnRedirectToLogin
事件仅由HandleChallengeAsync
中的HandleChallengeAsync 引发,因此感觉这是覆盖ChallengeResult
行为的正确位置。解决方案:
options.Events.OnRedirectToLogin = context =>
{
if (context.HttpContext?.User?.Identity?.IsAuthenticated == false)
{
//The user is not authenticated... Use the "oidc" challenge scheme
//and send them to identity server.
var task = context.HttpContext.ChallengeAsync("oidc");
task.WaitAndUnwrapException();
return Task.CompletedTask;
}
var accessDeniedPath = BuildRedirectUri(context.HttpContext, options.AccessDeniedPath);
context.Response.Redirect(accessDeniedPath);
context.Response.StatusCode = 302;
return Task.CompletedTask;
};
边注:
应该注意的是, AbpAuthorizationFilter
的默认行为并不反映 Asp.Net Core MVC 2.0 AuthorizeFilter
的股票行为。 当经过身份验证的用户授权失败时,Asp.Net Core MVC 2.0 AuthorizeFilter
返回 Forbid 结果。
Asp.Net Core MVC 的默认AuthorizeFilter
将AuthorizeFilter
委托给IPolicyEvaluator
。 如果授权失败且用户通过认证,则设置 Forbid 结果;如果授权失败且用户未通过身份验证,则设置 Challenge 结果。
var result = await _authorization.AuthorizeAsync(context.User, resource, policy);
if (result.Succeeded)
{
return PolicyAuthorizationResult.Success();
}
// If authentication was successful, return forbidden, otherwise challenge
return (authenticationResult.Succeeded)
? PolicyAuthorizationResult.Forbid()
: PolicyAuthorizationResult.Challenge();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.