C# 在哪里返回403禁止状态?
我正在使用授权路由获取数据,但由于该路由被禁止,因此我无法返回错误C# 在哪里返回403禁止状态?,c#,angular,asp.net-core,C#,Angular,Asp.net Core,我正在使用授权路由获取数据,但由于该路由被禁止,因此我无法返回错误 [Route("getTotal")] [HttpGet] [Authorize(Roles = "Admin")] public IActionResult GetTotalNumbers() { var test = User.Claims; try { var logic = new DrainlockLogic(_appSettings);
[Route("getTotal")]
[HttpGet]
[Authorize(Roles = "Admin")]
public IActionResult GetTotalNumbers()
{
var test = User.Claims;
try
{
var logic = new DrainlockLogic(_appSettings);
var ret = logic.GetTotalNumbers();
return Ok(ret);
}
catch (Exception e)
{
return StatusCode(500, e);
}
}
我的错误总是空的
this.homeService.getGratingNumbers()
.pipe(
map(itemData => {
return itemData.map(value => {
// return new ListItem(value.id, value.market, value.name);
this.pieChartLabels2.push([value.name]);
this.pieChartData2.push(value.id);
mybackgroundColor2.push(['#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6)])
})
})
)
.subscribe((listingItem) => {
console.log(listingItem) // gives an array of listingItem
},
error => console.log("oh no: " + error));
是否有适当的方法返回禁止角色访问的状态
问题是,如果我没有“Admin”角色,我就不会使用getTotalNumber()方法。因此,我不能返回我自己的状态。因此框架itslef返回403。我想将我自己的消息作为错误传递。调试代码并跟踪所有步骤。确保代码抛出错误
[Route("getTotal")]
[HttpGet]
[Authorize(Roles = "Admin")]
public IActionResult GetTotalNumbers()
{
var test = User.Claims;
try
{
var logic = new DrainlockLogic(_appSettings);
var ret = logic.GetTotalNumbers();
return Ok(ret);
}
catch (Exception e)
{
return StatusCode(500, e);
}
}
代码可能不会抛出错误
你确定这是抛出错误吗
var logic = new DrainlockLogic(_appSettings);
var ret = logic.GetTotalNumbers();
return Ok(ret);
我猜方法GetTolalNumbers返回null而不是抛出错误。正如我在您的问题下所评论的那样。您应该注意发送给客户机的详细消息。在这种情况下,提供所需的角色不是很危险。 您因拒绝用户访问而拥有的信息包含在
授权失败.FailedRequirements
中。这里我向您介绍如何提取它,因为默认的DefaultAuthorizationService
(属于IAuthorizationService
)不会将其传递给管道。详细管道从AuthorizeFilter
开始(可从AuthorizeAttribute
转换):
->->
因此,您可以看到,iaauthorizationservice.authorizationasync
的结果从AuthorizationResult
转换为PolicyAuthorizationResult
,其中包含的信息要少得多(当然会丢失所有故障
详细信息)。最后,PolicyAuthorizationResult
转换为banforresultl
或ChallengeResult
解决此问题的方法是通过继承DefaultAuthorizationService
创建自定义iaauthorizationservice
,并拦截对authorizationasync
的调用,将结果捕获到共享内存中,例如通过HttpContext.Features
。请注意,您可以利用第三方DI框架(如autofac
)提供的DI拦截器。这里我们使用内置的DI框架,因此这是帮助拦截调用的最佳解决方案
一旦授权后有了可用的AuthorizationResult
,您就可以提取故障
,并转换成一些友好的消息(注意不要暴露敏感信息)发送给客户端
代码如下:
public class HttpAppAuthorizationService : DefaultAuthorizationService, IAuthorizationService
{
readonly IHttpContextAccessor _httpContextAccessor;
public HttpAppAuthorizationService(IAuthorizationPolicyProvider policyProvider,
IAuthorizationHandlerProvider handlers,
ILogger<DefaultAuthorizationService> logger,
IAuthorizationHandlerContextFactory contextFactory,
IAuthorizationEvaluator evaluator,
IOptions<AuthorizationOptions> options,
IHttpContextAccessor httpContextAccessor) : base(policyProvider, handlers, logger, contextFactory, evaluator, options)
{
_httpContextAccessor = httpContextAccessor;
}
async Task<AuthorizationResult> IAuthorizationService.AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)
{
var result = await base.AuthorizeAsync(user, resource, requirements);
//capture the result for later using
_setAuthorizationResultFeature(result);
return result;
}
async Task<AuthorizationResult> IAuthorizationService.AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName)
{
var result = await base.AuthorizeAsync(user, resource, policyName);
//capture the result for later using
_setAuthorizationResultFeature(result);
return result;
}
void _setAuthorizationResultFeature(AuthorizationResult result)
{
var httpContext = _httpContextAccessor.HttpContext;
if(httpContext != null)
{
httpContext.Features.Set<IAuthorizationResultFeature>(new AuthorizationResultFeature(result));
}
}
}
public interface IAuthorizationResultFeature
{
AuthorizationResult AuthorizationResult { get; }
}
public class AuthorizationResultFeature : IAuthorizationResultFeature
{
public AuthorizationResultFeature(AuthorizationResult result)
{
AuthorizationResult = result;
}
public AuthorizationResult AuthorizationResult { get; }
}
现在,在iasyncalwaysrunsultfilter
的过滤器中,您可以提取iaauthorizationresultfeature
以获取详细故障并将其转换为所需的结果:
public class CustomAsyncAlwaysRunResultFilterAttribute : Attribute, IAsyncAlwaysRunResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
var msg = "";
var authorizationResult = context.HttpContext.Features.Get<IAuthorizationResultFeature>()?.AuthorizationResult;
if(authorizationResult?.Failure != null ) {
var rolesRequirements = authorizationResult.Failure.FailedRequirements.OfType<RolesAuthorizationRequirement>();
msg = $@"You need to have all following roles (each group requires at least one role):
{string.Join(", ", rolesRequirements.Select(e => $"({string.Join(", ", e.AllowedRoles)})"))}";
//sends back a plain text result containing the msg
//this can be obtained by the client
context.Result = new ContentResult { Content = msg, StatusCode = 403 };
}
await next();
}
}
public类customAsyncAlwaysRunsultFilterAttribute:属性,IAsyncalwaysRunsultFilter
{
ResultExecutionAsync上的公共异步任务(ResultExecutionContext,ResultExecutionDelegate next)
{
var msg=“”;
var authorizationResult=context.HttpContext.Features.Get()?.authorizationResult;
if(授权结果?.Failure!=null){
var rolesRequirements=authorizationResult.Failure.FailedRequirements.OfType();
msg=$@“您需要具有以下所有角色(每个组至少需要一个角色):
{string.Join(“,”,rolesRequirements.Select(e=>$”({string.Join(“,”,e.AllowedRoles)})”)}”;
//发回包含消息的纯文本结果
//这可由客户获得
context.Result=newcontentresult{Content=msg,StatusCode=403};
}
等待下一个();
}
}
实际上,您也可以在格式化消息的过程中使用其他类型的授权要求。上面的代码只是一个仅格式化RolesAuthorizationRequirement
的示例(适合您的具体情况)
iasyncalwaysrunsultfilter
应该全局注册(与其他类型的过滤器一样)。我希望您知道如何做到这一点(谷歌搜索肯定会为您提供一个快速的结果)。如果您正确地应用了403
,框架将返回该。您也可以通过返回return bankeen(),手动将其返回代码>-你到底想要什么?没错,我得到了403的框架。但是我想传递我自己的消息,如果我的角色不正确,这是不可能的。看起来您想提供有关用户被拒绝访问的详细信息。我认为这样做不是一个好的做法。详细信息可能是一个安全问题。在这种情况下,一般的信息要好得多。这就像当登录失败时,我们没有清楚地提供关于用户不存在或密码不正确的消息,我们只是返回一条消息,说类似“未成功”。这也很难实现,当前的授权管道需要许多AuthorizationHandler进行授权,我相信结果中没有提供具体的原因。看起来它未经授权的原因可以从失败需求列表中提取出来,该列表包含在AuthorizationFailure.FailedRequests
(在使用授权中间件时)。但是,正如我所说,在向客户提供更详细的信息时,您应该小心。我认为这就是解决方案。谢谢。很抱歉我的解释不好。如果我没有“管理员”角色我不能返回任何东西,因为我没有进入方法本身。我从框架中得到403,但我想传递我自己的消息