代码之家  ›  专栏  ›  技术社区  ›  Luis Abreu

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

  •  0
  • Luis Abreu  · 技术社区  · 7 年前

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

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

    如果这是一个简单的aspnet核心应用程序,那么我只需将lambda传递给 OnRedirectToLogin 处理请求的cookie处理程序的属性。不幸的是,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 identity来管理用户帐户。。。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Luis Abreu    7 年前

    在这里发布答案,以防有人感兴趣。。。

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

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

    axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    
        2
  •  0
  •   Vidmantas Blazevicius    7 年前

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

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

    只需要注册启动。反恐精英:

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