【问题标题】:ASP.NET Core Identity 2.0 - Return 401 status code to ajax functionASP.NET Core Identity 2.0 - 将 401 状态代码返回给 ajax 函数
【发布时间】:2019-02-11 08:18:36
【问题描述】:

我有一个使用 Identity 2.0 的 ASP.NET Core 应用程序。我试图在用户未登录时返回 401 状态代码(或在他未授权时返回 403),但不同的函数仅返回 302 代码...

我根据我的应用需求进行了设置:

  • 个性化的[授权]方法

    [HttpPost]
    [RequiresPermission("Projects.Creation, Projects.Modification")]
    public IActionResult SaveProject(Project prj)
    {
     (...)
    {
    

我的 RequiresPermission 是一个继承 TypeFilterAttribute 的类,并且有一个似乎对设置不同返回结果很有用的函数:

 public async Task OnResourceExecutionAsync(ResourceExecutingContext context,
                                                   ResourceExecutionDelegate next)
        {
            var principal = new CustomPrincipal(_PermissionProvider, context.HttpContext.User.Identity);
            bool isInOneOfThisRole = false;
            foreach (var item in _requiredPermissions.RequiredPermissions)
            {
                if (principal.IsInRole(item))
                {
                    isInOneOfThisRole = true;
                }
            }

            if (isInOneOfThisRole == false)
            {
                if (principal.Identity.IsAuthenticated)
                {
                    context.Result = new UnauthorizedResult();
                }
                else
                {
                    context.Result = new RedirectResult("~/Connexion/Login");
                }

                await context.Result.ExecuteResultAsync(context);
            }
            else
            {
                await next();
            }
        }
  • 我的启动方法中的不同之处

    services.AddIdentity<Utilisateur, Profil>().AddUserManager<CustomUserManager<Utilisateur>>().AddRoleManager<CustomRoleManager>().AddDefaultTokenProviders();
    services.AddTransient<IUserStore<Utilisateur>, UserStore>();
    services.AddTransient<IRoleStore<Profil>, ProfileStore>();
    services.AddTransient<IPermissionProvider, PermissionProvider>();
    
    services.Configure<IdentityOptions>(options =>
    {
        // Lockout settings
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
        options.Lockout.MaxFailedAccessAttempts = 10;
        options.Lockout.AllowedForNewUsers = true;
        //options.SecurityStampValidationInterval = TimeSpan.FromHours(2);
    });
    
    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
        // If the LoginPath isn't set, ASP.NET Core defaults the path to /Account/Login.
        options.LoginPath = new PathString("/Connexion/Login");
        options.LogoutPath = new PathString("/Connexion/SignedOut");
        // If the AccessDeniedPath isn't set, ASP.NET Core defaults the path to /Account/AccessDenied.
        options.AccessDeniedPath = new PathString("/Connexion/AccessDenied");
        options.SlidingExpiration = true;
    });
    

我已经尝试了很多建议,但似乎都没有这样的效果:

services.ConfigureApplicationCookie(options =>
{
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.StatusCode = 401;    
        return Task.CompletedTask;
    };
});

这个解决方案对我来说不是一个好的解决方案,因为它重定向了 ajax 和非 ajax 方法,这破坏了我的其他重定向......

我还尝试用我在网上找到的一个类来覆盖 AuthorizeAttribute 类。这个类似乎是我想要的,但它不适用于 ASP.Net Core...

using Microsoft.AspNetCore.Authorization;
using System.Net;

public class ApplicationAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        var httpContext = filterContext.HttpContext;
        var request = httpContext.Request;
        var response = httpContext.Response;
        var user = httpContext.User;

        if (request.IsAjaxRequest())
        {
            if (user.Identity.IsAuthenticated == false)
                response.StatusCode = (int)HttpStatusCode.Unauthorized;
            else
                response.StatusCode = (int)HttpStatusCode.Forbidden;

            response.SuppressFormsAuthenticationRedirect = true;
            response.End();
        }

        base.HandleUnauthorizedRequest(filterContext);
    }
}

你有想法解决我的问题吗?或者我做错了什么。

【问题讨论】:

  • RequiresPermission 属性如何工作?这是自定义属性吗?
  • @Brad 编辑完成。我添加了我的 PermissionAttribute 类的主要功能。

标签: c# ajax asp.net-core asp.net-core-2.0 asp.net-identity-2


【解决方案1】:

多亏了布拉德,我找到了解决方案,真是太愚蠢了……

我不需要 ApplicationAuthorizeAttribute 课程,因为我已经有了 RequiresPermissionAttribute 课程。

问题出在我的函数 OnResourceExecutionAsync() 中:

  • 当用户没有权限时我返回了错误的代码(未经授权而不是禁止结果)
  • 当我的用户未登录时,我向我的登录页面返回了 redirectResult 而不是 StatusResult。我将其更改为 UnauthorizedResult()。

更改了我的部分功能:

            if (isInOneOfThisRole == false)
            {
                if (principal.Identity.IsAuthenticated)
                {
                    context.Result = new ForbidResult();
                }
                else
                {
                    context.Result = new UnauthorizedResult();
                }

                await context.Result.ExecuteResultAsync(context);
            }
            else
            {
                await next();
            }

我的 ajax 中已经有一个函数可以捕获不同的状态码:

$(document).ajaxError(function (xhr, props) {
    if (props.status == 403) {
        window.location = window.location.protocol + '//' + window.location.host + "/Connexion/AccessDenied";
    } else if (props.status == 401) {
        window.location = window.location.protocol + '//' + window.location.host + "/Connexion/Login";
    }
});

一切运行良好!

【讨论】:

    猜你喜欢
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 2017-07-10
    • 2020-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    相关资源
    最近更新 更多