Identityserver4 Identity server 4:拦截302并将其替换为401

Identityserver4 Identity server 4:拦截302并将其替换为401,identityserver4,Identityserver4,我有一个应用程序,它同时托管Identity Server 4和一个客户端应用程序(Vue),它使用一个区域中定义的两个rest服务来管理站点。其思想是,与特定角色关联的用户可以访问客户端应用程序并调用rest服务来执行操作 目前,我的问题是,当用户不属于管理员角色时,api返回302。我想把它改成401,但我遇到了一些问题 如果这是一个简单的aspnet核心应用程序,那么我只需将lambda传递给负责请求的cookie处理程序的OnRedirectToLogin属性。不幸的是,IS4只允许我设

我有一个应用程序,它同时托管Identity Server 4和一个客户端应用程序(Vue),它使用一个区域中定义的两个rest服务来管理站点。其思想是,与特定角色关联的用户可以访问客户端应用程序并调用rest服务来执行操作

目前,我的问题是,当用户不属于管理员角色时,api返回302。我想把它改成401,但我遇到了一些问题

如果这是一个简单的aspnet核心应用程序,那么我只需将lambda传递给负责请求的cookie处理程序的
OnRedirectToLogin
属性。不幸的是,IS4只允许我设置cookie的一些基本设置(过期和滑动)。同样,我可以重写cookie处理程序。因此,我尝试了以下几点:

services.AddIdentityServer()
  ... // other configurations

services.AddAuthentication(sharedOptions => {
            sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;//IdentityServerConstants.ExternalCookieAuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = IdentityServerConstants.SignoutScheme;

})
... //other external providers...
.AddCookie( CookieAuthenticationDefaults.AuthenticationScheme, options => {
     options.Events = new CookieAuthenticationEvents {
        OnRedirectToLogin = ctx => {
          if (ctx.Request.Path.StartsWithSegments("/Admin", StringComparison.OrdinalIgnoreCase)) {
               ctx.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
          }
          return Task.CompletedTask;                                                                                                   
         };
      });
我希望每当请求被重定向到登录页面时,我的处理程序都会被调用,但这种情况从未发生过。有人能帮忙吗

谢谢


编辑:只需补充一点,我也在使用aspnet identity来管理用户帐户…

不久前,我为这个目的编写了一个中间件,从未回头看,因此如果您没有找到更好的解决方案,也许该解决方案也可以帮助您:

public class RedirectHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RedirectHandlingMiddleware> _logger;

    public RedirectHandlingMiddleware(RequestDelegate next, ILogger<RedirectHandlingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        await HandleRedirect(context, ex);
        await _next(context);
    }

    private Task HandleRedirect(HttpContext context)
    {
        if (context.Request.Path.StartsWithSegments("/Admin", StringComparison.OrdinalIgnoreCase) && context.Response.StatusCode == 302)
        {
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        }
        return Task.CompletedTask;
    }
}
公共类重定向处理中间件
{
private readonly RequestDelegate\u next;
专用只读ILogger\u记录器;
公共重定向处理中间件(RequestDelegate next,ILogger logger)
{
_下一个=下一个;
_记录器=记录器;
}
公共异步任务调用(HttpContext上下文)
{
wait HandleRedirect(上下文,ex);
等待下一步(上下文);
}
私有任务HandleRedirect(HttpContext上下文)
{
if(context.Request.Path.StartsWithSegments(“/Admin”,StringComparison.ordinallingorecase)和&context.Response.StatusCode==302)
{
context.Response.StatusCode=(int)HttpStatusCode.Unauthorized;
}
返回Task.CompletedTask;
}
}
只需在Startup.cs中注册:

        app.UseAuthentication();
        app.UseMiddleware<RedirectHandlingMiddleware>();
app.UseAuthentication();
app.UseMiddleware();

在此处发布答案,以防有人感兴趣

经过一些挖掘,我发现使用identity意味着你不能像我那样定制cookie处理程序。幸运的是,可以由
configureApplicationOkie
扩展方法配置的
ConfigureAuthenticationEvent
已经做了正确的事情:如果它检测到当前请求是AJAX调用,它将返回401;如果不是,它将返回302。问题是:vue客户端发出的请求没有被视为AJAX请求,因为它没有将
X-request-With
头设置为
XMLHttpRequest

因此,只需将axios配置为在所有调用中设置标头:

axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

你好我尝试在UseIdentityServer调用后注册中间件,但它不起作用…@LuisAbreu实际上我给你的代码不正确,永远不会起作用,请尝试新代码。