身份服务器4:拦截302并将其替换为401

时间:2019-02-06 14:52:24

标签: identityserver4

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

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

如果这是一个简单的aspnet核心应用程序,那么我只需将一个lambda传递给处理请求的cookie处理程序的OnRedirectToLogin属性。不幸的是,IS4仅允许我设置Cookie的几个基本设置(过期和滑动)。同样的docs说,我可以覆盖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身份来管理用户帐户...

2 个答案:

答案 0 :(得分:1)

如果有人感兴趣的话,在这里发布答案...

经过一番挖掘,我发现使用身份意味着您无法通过执行自己的操作来自定义Cookie处理程序。幸运的是,可以通过ConfigureAuthenticationEvent扩展方法配置的ConfigureApplicationCookie已经做了正确的事情:如果它检测到当前请求是AJAX调用,它将返回401;否则,它将返回401。如果不是,它将返回302。这就是问题所在:来自vue客户端的请求未被视为AJAX请求,因为它没有将X-Request-With标头设置为XMLHttpRequest。 / p>

因此,所需要做的就是配置axios以在所有调用中设置标题:

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

答案 1 :(得分:0)

我前一段时间为此目的编写了一个中间件,并且从没有回过头,所以如果您找不到更好的解决方案,也许该解决方案也可以为您提供帮助:

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;
    }
}

只需在Startup.cs中注册:

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