ASP.NET Core Identity 2.0 - Return 401 状态码到 ajax 函数
ASP.NET Core Identity 2.0 - Return 401 status code to ajax function
我有一个 ASP.NET 核心应用程序,我在其中使用 Identity 2.0。我正在尝试 return 用户未登录时的 401 状态代码(或当他未授权时为 403),但不同的功能 return 只有 302 代码...
我根据我的应用需求进行了设置:
个性化的[授权]方法
[HttpPost]
[RequiresPermission("Projects.Creation, Projects.Modification")]
public IActionResult SaveProject(Project prj)
{
(...)
{
我的 RequiresPermission 是一个 class,它继承了 TypeFilterAttribute 并且有一个函数似乎对设置不同的 returned 结果很有用:
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 方法,这破坏了我的其他重定向...
我还尝试用我在网上找到的 class 覆盖 AuthorizeAttribute class。这个class似乎是我想要的但是它对ASP.Net核心不起作用...
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);
}
}
你有解决我问题的想法吗?或者我做错了什么。
感谢 Brad,我找到了解决方案,但它太愚蠢了...
我不需要 ApplicationAuthorizeAttribute
class 因为我已经有了 RequiresPermissionAttribute
class.
问题出在我的函数 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";
}
});
而且一切正常!
我有一个 ASP.NET 核心应用程序,我在其中使用 Identity 2.0。我正在尝试 return 用户未登录时的 401 状态代码(或当他未授权时为 403),但不同的功能 return 只有 302 代码...
我根据我的应用需求进行了设置:
个性化的[授权]方法
[HttpPost] [RequiresPermission("Projects.Creation, Projects.Modification")] public IActionResult SaveProject(Project prj) { (...) {
我的 RequiresPermission 是一个 class,它继承了 TypeFilterAttribute 并且有一个函数似乎对设置不同的 returned 结果很有用:
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 方法,这破坏了我的其他重定向...
我还尝试用我在网上找到的 class 覆盖 AuthorizeAttribute class。这个class似乎是我想要的但是它对ASP.Net核心不起作用...
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);
}
}
你有解决我问题的想法吗?或者我做错了什么。
感谢 Brad,我找到了解决方案,但它太愚蠢了...
我不需要 ApplicationAuthorizeAttribute
class 因为我已经有了 RequiresPermissionAttribute
class.
问题出在我的函数 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";
}
});
而且一切正常!