MVC.Net核心MVC 21中HttpContext的插件授权头

MVC.Net核心MVC 21中HttpContext的插件授权头,.net,model-view-controller,asp.net-core,.net,Model View Controller,Asp.net Core,我在.Net Core 2.1应用程序的会话中存储了一个Jwt承载令牌。在我的中间件中,我通过以下方式拦截请求并将令牌附加到头: httpContext.Request.Headers.Add("Authorization", $"Bearer {token}"); 这目前不起作用,因为我在受保护的路线上遇到未经授权的攻击。如果我使用邮递员进行相同的呼叫,并在报头中传递授权和承载令牌,那么它可以工作 我需要对http.Request做什么更改才能使其可接受 使用Jwt启动的部分: var si

我在.Net Core 2.1应用程序的会话中存储了一个Jwt承载令牌。在我的中间件中,我通过以下方式拦截请求并将令牌附加到头:

httpContext.Request.Headers.Add("Authorization", $"Bearer {token}");
这目前不起作用,因为我在受保护的路线上遇到未经授权的攻击。如果我使用邮递员进行相同的呼叫,并在报头中传递授权和承载令牌,那么它可以工作

我需要对http.Request做什么更改才能使其可接受

使用Jwt启动的部分: var signingKey=密钥

        services.AddSingleton<IJwtFactory, JwtFactory>();

        var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));

        // Configure JwtIssuerOptions
        services.Configure<JwtIssuerOptions>(options =>
        {
            options.Issuer = Issuer;
            options.Audience = Audience;
            options.SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
        });

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.SaveToken = true;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = Issuer,

                    ValidateAudience = true,
                    ValidAudience = Audience,

                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = signingKey,

                    RequireExpirationTime = false,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                };
            })
            .AddCookie(cfg => cfg.SlidingExpiration = true);

如评论中所述,在调用
UseSiteRouteMiddleware
时,身份验证中间件已经处理完毕

所以现在做任何事情都太晚了。更改中间件的执行顺序。 在
useAuthentication()之前,将
useSiteRouteMiddlware
放在靠近开头的位置

根据注册顺序确定中间件的执行顺序

启动中添加中间件组件的顺序。Configure
方法定义在请求时调用中间件组件的顺序以及响应的相反顺序。订单对于安全性、性能和功能至关重要

这就是注册身份验证中间件的原因,该中间件最终将在传入的HTTP请求中查找JWT承载令牌,并使用该令牌基于该值对用户进行身份验证

由于该中间件是您注册的第一个中间件,因此它也将作为第一个中间件运行,然后再运行管道中的任何其他中间件。由于
app.UseSiteRouteMiddleware()
调用稍后进行,因此修改传入HTTP请求的自定义中间件也将稍后运行。因此,它将在请求已用于身份验证目的后修改该请求

如果希望在有机会重写HTTP请求后进行身份验证,则必须将
app.UseSiteRouteMiddleware()移动到
app.UseAuthentication()调用之前

但是请注意,由于自定义中间件使用会话,因此会话中间件也必须在自定义中间件之前运行。毕竟,您的流程应该是这样工作的:

  • 检索会话信息(会话中间件)
  • 调整HTTP请求头(SiteRouteMiddleware)
  • 验证用户(验证中间件)
  • 因此,您必须按此顺序设置这三个中间件:

    app.UseSession();
    app.UseSiteRouteMiddleware(getRoutes);
    app.UseAuthentication();
    

    也就是说,您存储JWT的方法非常不统一。使用承载令牌的身份验证通常被认为是无状态的,因为客户端显式地传递对用户进行身份验证所需的令牌。这与常见的基于cookie的身份验证不同,在这种身份验证中,数据作为请求的一部分隐式地通过cookie传递

    具有讽刺意味的是,使用会话中间件存储JWT承载令牌实际上正是这样做的:默认情况下,会话中间件使用会话cookie恢复以前的用户会话。因此,对于您的解决方案,您基本上使用了不同的cookie来启用身份验证

    除非您对此设计有很好的理由,否则我强烈建议您切换到标准的cookie身份验证,它只将身份存储在cookie中,而不是存储在JSON Web令牌中。这通常也会降低身份验证设置的复杂性,同时使其得到更好的支持。同时,您还将失去使用额外会话管理的要求,这通常被建议不要使用(除非您有充分的理由)


    如果您需要“正常”的JWT承载身份验证,例如,如果您的应用程序也被API客户端访问,那么请注意,在应用程序中同时使用JWT承载身份验证和cookie身份验证并没有什么错。这样,您就可以自由选择最适合每种情况的身份验证样式。

    显示您的配置代码,否则我们将无法帮助您猜测
    UseXxx
    方法部分仍然缺少配置部分。中间件是按照它们注册到
    UseXxx
    middleware的顺序执行的,因此,如果您在认证中间件之前或之后注册中间件,那么这一部分可能仍然很重要,正如我所想的那样。调用
    UseSiteRouteMiddle软件时,身份验证中间件已经处理完毕。更改顺序,将您的
    useSiteRouteMiddle软件
    放在靠近开头的位置,然后再将其固定在
    useAuthentication
    之前。谢谢你的帮助。
    app.UseAuthentication();
    
    app.UseSession();
    app.UseSiteRouteMiddleware(getRoutes);
    app.UseAuthentication();