为什么我需要设置一个DefaultForbidScheme [英] Why do i need to set a DefaultForbidScheme

查看:163
本文介绍了为什么我需要设置一个DefaultForbidScheme的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在WebAPI .net核心项目中,我创建了一个中间件类来验证api密钥.通过对其进行验证,它会检索密钥在invoke方法内具有的权限(用户或管理员).

In a WebAPI .net core project I have created a Middleware class that validates an api key. From validating it, it retrieves the permissions that the key has (user or admin) within the invoke method.

我通过一个开关将其设置为这样的原理

I pass it through a switch to set the principle like so

GenericIdentity identity = new GenericIdentity("API");
GenericPrincipal principle = null;

          //we have a valid api key, so set the role permissions of the key
          switch (keyValidatorRes.Role)
           {
               case Roles.User:
                    principle = new GenericPrincipal(identity, new[] { "User" });  
                    context.User = principle;
                    break;
                case Roles.Admin:
                    principle = new GenericPrincipal(identity, new[] { "Admin" });         
                    context.User = principle;
                    break;
                default:
                    principle = new GenericPrincipal(identity, new[] { "Other" });
                    context.User = principle;
                    break;
                    }

在控制器上,我有方法
[Authorize(Roles = "Admin")]

On controllers methods I have
[Authorize(Roles = "Admin")]

验证经过身份验证的api密钥的作用

to validate the roles of an authenticated api key

如果用户具有管理原则,则按预期进行.但是,如果它具有用户或其他原理,那么我会收到关于

If the user has the admin principle it goes through as expected. However, if it has a user or other principle then I get an error about

没有DefaultForbidScheme

not having a DefaultForbidScheme

我到处搜索并通过客户计划将身份验证添加到我的startup.cs中

I googled around and added Authentication to my startup.cs with a customer scheme

services.AddAuthentication(options=> {
       options.DefaultForbidScheme = "forbidScheme";
       options.AddScheme<AuthSchemeHandle>("forbidScheme", "Handle Forbidden");
});

并创建了 AuthSchemeHandle

public class AuthSchemeHandle : IAuthenticationHandler
    {
        private HttpContext _context;

        public Task<AuthenticateResult> AuthenticateAsync()
        {
            return Task.FromResult(AuthenticateResult.NoResult());
        }

        public Task ChallengeAsync(AuthenticationProperties properties)
        {
            throw new NotImplementedException();
        }

        public Task ForbidAsync(AuthenticationProperties properties)
        {
            return Task.FromResult(AuthenticateResult.Fail("Failed Auth"));
        }

        public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
        {
            _context = context;
            return Task.CompletedTask;
        }
    }

现在,如果该原则没有Admin,它将失败,并且没有错误,但是API返回的响应为200,没有任何内容.我希望收到4xx响应,并显示消息身份验证失败"

Now if the principle does not have Admin it fails without the error but the response that is returned on the API is 200 with no content. I was expecting a 4xx response with the message "Failed Auth"

我只是在试图弄清为什么它看起来不像预期的那样固定",我不明白它是如何固定的.

I am just trying to work out why it is not as expected as although it seems "fixed" I do not understand how it has fixed it.

我应该有更好的方法吗?

Is there a better way that I should be doing this?

问候 标记

推荐答案

为什么它似乎不像预期的那样修复",所以我不明白它是如何修复的.

why it is not as expected as although it seems "fixed" I do not understand how it has fixed it.

当身份验证处理程序调用IAuthenticationHandler.ForbidAsync()方法时,没有黑魔法.我们必须自己做相关的事情.简而言之,根据需要设置StatusCode=403.

There's no dark magic when the authentication handler calls IAuthenticationHandler.ForbidAsync() method. We have to do relevant things ourself. In short, setting the StatusCode=403 as your need.

public async Task ForbidAsync(AuthenticationProperties properties)
{
    properties = properties ?? new AuthenticationProperties();
    _context.Response.StatusCode = 403;
    // ...
    return Task.CompletedTask;    
}

请注意,您不必返回Task.FromResult(),因为它并不关心结果.

As a side note, you don't need return a Task.FromResult() as it doesn't care about the result.

我应该有更好的方法吗?

Is there a better way that I should be doing this?

ASP.NET核心团队为我们提供了一个抽象类AuthenticationHandler来处理身份验证.该抽象类具有 ForbidAsync(AuthenticationProperties properties) (以及其他公共方法).因此,如下扩展该抽象类非常容易:

The ASP.NET Core Team provides us an abstract class AuthenticationHandler to handle authentication. This abstract class has a built-in implementation for ForbidAsync(AuthenticationProperties properties) (and also for other public methods). So it's much easy to extends this abstract class as below:

public class MyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    public MyAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) 
        : base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        return AuthenticateResult.NoResult();
    }
}

最后,添加身份验证服务的配置:

Finally, add a configuration for authentication service:

services
    .AddAuthentication(options=>{
        options.DefaultAuthenticateScheme = "forbidScheme";
        options.DefaultForbidScheme = "forbidScheme";
        options.AddScheme<MyAuthenticationHandler>("forbidScheme", "Handle Forbidden");
    });

它应该可以正常工作.

这篇关于为什么我需要设置一个DefaultForbidScheme的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆