在ASP.Net Core中重写AuthorizeAttribute并响应Json状态 [英] Override AuthorizeAttribute in ASP.Net Core and respond Json status

查看:311
本文介绍了在ASP.Net Core中重写AuthorizeAttribute并响应Json状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从ASP.Net Framework转到ASP.Net Core.

I'm moving from ASP.Net Framework to ASP.Net Core.

在带有Web API 2项目的ASP.Net Framework中,我可以像这样自定义AuthorizeAttribute:

In ASP.Net Framework with Web API 2 project, I can customize AuthorizeAttribute like this :

public class ApiAuthorizeAttribute : AuthorizationFilterAttribute
{
    #region Methods

    /// <summary>
    ///     Override authorization event to do custom authorization.
    /// </summary>
    /// <param name="httpActionContext"></param>
    public override void OnAuthorization(HttpActionContext httpActionContext)
    {
        // Retrieve email and password.
        var accountEmail =
            httpActionContext.Request.Headers.Where(
                    x =>
                        !string.IsNullOrEmpty(x.Key) &&
                        x.Key.Equals("Email"))
                .Select(x => x.Value.FirstOrDefault())
                .FirstOrDefault();

        // Retrieve account password.
        var accountPassword =
            httpActionContext.Request.Headers.Where(
                    x =>
                        !string.IsNullOrEmpty(x.Key) &&
                        x.Key.Equals("Password"))
                .Select(x => x.Value.FirstOrDefault()).FirstOrDefault();

        // Account view model construction.
        var filterAccountViewModel = new FilterAccountViewModel();
        filterAccountViewModel.Email = accountEmail;
        filterAccountViewModel.Password = accountPassword;
        filterAccountViewModel.EmailComparision = TextComparision.Equal;
        filterAccountViewModel.PasswordComparision = TextComparision.Equal;

        // Find the account.
        var account = RepositoryAccount.FindAccount(filterAccountViewModel);

        // Account is not found.
        if (account == null)
        {
            // Treat the account as unthorized.
            httpActionContext.Response = httpActionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);

            return;
        }

        // Role is not defined which means the request is allowed.
        if (_roles == null)
            return;

        // Role is not allowed 
        if (!_roles.Any(x => x == account.Role))
        {
            // Treat the account as unthorized.
            httpActionContext.Response = httpActionContext.Request.CreateResponse(HttpStatusCode.Forbidden);

            return;
        }

        // Store the requester information in action argument.
        httpActionContext.ActionArguments["Account"] = account;
    }

    #endregion

    #region Properties

    /// <summary>
    ///     Repository which provides function to access account database.
    /// </summary>
    public IRepositoryAccount RepositoryAccount { get; set; }

    /// <summary>
    ///     Which role can be allowed to access server.
    /// </summary>
    private readonly byte[] _roles;

    #endregion

    #region Constructor

    /// <summary>
    ///     Initialize instance with default settings.
    /// </summary>
    public ApiAuthorizeAttribute()
    {
    }

    /// <summary>
    ///     Initialize instance with allowed role.
    /// </summary>
    /// <param name="roles"></param>
    public ApiAuthorizeAttribute(byte[] roles)
    {
        _roles = roles;
    }

    #endregion
}

在我自定义的AuthorizeAttribute中,我可以检查帐户是否有效并将带有消息的HttpStatusCode返回给客户端.

In my customized AuthorizeAttribute, I can check whether account is valid or not and return HttpStatusCode with message to client.

我正在尝试在ASP.Net Core中执行相同的操作,但是没有OnAuthorization可供我覆盖.

I'm trying to do the samething in ASP.Net Core, but no OnAuthorization for me to override.

如何实现与ASP.Net Framework中相同的功能?

How can I achieve the same thing as in ASP.Net Framework ?

谢谢

推荐答案

您正在错误地处理此问题.从未真正鼓励为此编写自定义属性或扩展现有属性.使用 ASP.NET Core 角色仍然是系统的一部分,以实现向后兼容,但现在不鼓励使用它们.

You're approaching this incorrectly. It never was really encouraged to write custom attributes for this, or to extend existing. With ASP.NET Core roles are still apart of the system for backwards compatibility but they are now also discouraged.

关于驱动架构的一些变化及其应采用的方式,共分为2部分,非常有趣.

There is a great 2 part series on some of the driving architecture changes and the way that this is and should be utilized found here. If you want to still rely on roles you can do so, but I would suggest using policies.

要制定政策,请执行以下操作:

To wire a policy do the following:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthorization(options =>
    {
        options.AddPolicy(nameof(Policy.Account), 
                          policy => policy.Requirements.Add(new AccountRequirement()));
    });

    services.AddSingleton<IAuthorizationHandler, AccountHandler>();
}

为方便起见,我创建了Policy枚举.

I created a Policy enum for convenience.

public enum Policy { Account };

这样装饰入口点:

[
    HttpPost,
    Authorize(Policy = nameof(Policy.Account))
]
public async Task<IActionResult> PostSomething([FromRoute] blah)
{
}

AccountRequirement只是一个占位符,它需要实现IAuthorizationRequirement接口.

The AccountRequirement is just a placeholder, it needs to implement the IAuthorizationRequirement interface.

public class AccountRequirement: IAuthorizationRequirement { }

现在,我们只需要创建一个处理程序并将其连接为DI.

Now we simply need to create a handler and wire this up for DI.

public class AccountHandler : AuthorizationHandler<AccountRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        AccountRequirement requirement)
    {
        // Your logic here... or anything else you need to do.
        if (context.User.IsInRole("fooBar"))
        {
            // Call 'Succeed' to mark current requirement as passed
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

其他资源

这篇关于在ASP.Net Core中重写AuthorizeAttribute并响应Json状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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