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

查看:22
本文介绍了为什么我需要设置一个 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")]

验证经过身份验证的 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 Core 团队为我们提供了一个抽象类 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天全站免登陆