在 MVC .Net Core Mvc 21 中将授权标头添加到 HttpContext

bno*_*man 5 .net model-view-controller asp.net-core

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

httpContext.Request.Headers.Add("Authorization", $"Bearer {token}");
Run Code Online (Sandbox Code Playgroud)

目前此功能不起作用,因为我在受保护的路线上获得了未经授权的权限。如果我使用邮递员进行相同的调用并在标头中传递授权和承载令牌,则它可以工作。

我需要对 http.Request 进行哪些更改才能使其可接受?

使用 Jwt 启动的部分: varsigningKey = key;

        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);
Run Code Online (Sandbox Code Playgroud)

配置:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        app.UseAuthentication();
        app.UseStaticFiles();
        app.UseSession();
        app.UseHttpContextLogging();
        app.ConfigureErrorHandling(env);
        app.UseSiteRouteMiddleware(getRoutes); -- Middleware that intercepts the request, adding the token here
        app.UseRequestLocalization();
        app.UseRewriter();
        app.UseMvc(getRoutes);
    }
Run Code Online (Sandbox Code Playgroud)

pok*_*oke 1

app.UseAuthentication();\n
Run Code Online (Sandbox Code Playgroud)\n\n

这就是注册身份验证中间件的内容,该中间件最终将在传入的 HTTP 请求中查找 JWT 承载令牌,并使用它根据该值对用户进行身份验证。

\n\n

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

\n\n

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

\n\n

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

\n\n
    \n
  1. 检索会话信息(会话中间件)
  2. \n
  3. 调整HTTP请求标头(SiteRouteMiddleware)
  4. \n
  5. 认证用户(认证中间件)
  6. \n
\n\n

因此,您必须按顺序设置这三个中间件:

\n\n
app.UseSession();\napp.UseSiteRouteMiddleware(getRoutes);\napp.UseAuthentication();\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

话虽如此,您存储 JWT 的方法相当不传统。使用不记名令牌的身份验证通常被认为是无状态的,因为客户端显式传递验证用户身份所需的令牌。这与常见的基于 cookie 的身份验证相反,在常见的身份验证中,数据作为请求的一部分通过 cookie 隐式传递。

\n\n

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

\n\n

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

\n\n

如果您需要 \xe2\x80\x9cnormal\xe2\x80\x9d JWT 不记名身份验证,例如,如果您的应用程序也由 API 客户端访问,那么请注意,同时使用 JWT 不记名身份验证和cookie身份验证没有任何问题。你的申请。这样,您就可以自由选择最适合每种情况的身份验证方式。

\n