【问题标题】:IHttpContextAccessor session invalid operation exception in CustomClaimsTransformerCustomClaimsTransformer 中的 IHttpContextAccessor 会话无效操作异常
【发布时间】:2018-08-30 10:30:41
【问题描述】:

我按照官方文档从 CustomClaimsTransformer 中的自定义组件访问 HttpContext。

我之前有一个 .NET Core Web 应用程序,我在其中使用会话使管理员能够以不同用户的视图(身份)跳转到应用程序(出于支持目的)。我存储信息,应在会话中为哪个用户准备视图。现在我想让它更优雅,并通过声明和基于角色的授权来使用 .net 核心授权。由于后面有 Windows 身份验证,我必须使用 CustomClaimsTransformer。现在我的问题是,我想从 CustomClaimsTransformer 中访问当前会话。我可以注入 IHttpContextAccessor,但 IHttpContextAccessor.Session 总是引发无效操作异常。

Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
        options =>
        {
            options.LoginPath = new PathString("/Account/Login/");
            options.AccessDeniedPath = new PathString("/Account/Forbidden/");
        });
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });
        services.AddAuthorization(options =>
        {
            options.AddPolicy("RequireAdministratorRole", policy => policy.RequireClaim(ClaimTypes.Role, "admin"));
            options.AddPolicy("Test1", policy => policy.RequireClaim("Rechte", " Test1"));
            options.AddPolicy("Test2", policy => policy.RequireClaim("Rechte", " Test2"));

        });

        services.AddMvc(config =>
             {
                 var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                 config.Filters.Add(new AuthorizeFilter(policy));
             }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        //services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddHttpContextAccessor();
        services.AddTransient<IClaimsTransformation, CustomClaimsTransformer>();
        services.AddDistributedMemoryCache();
        services.AddSession();
    }

CustomClaimsTransformer:

CustomClaimsTransformer:
public class CustomClaimsTransformer : IClaimsTransformation
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public CustomClaimsTransformer(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }


    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var z = _httpContextAccessor.HttpContext; //works
        var zz = _httpContextAccessor.HttpContext.Session; // System.InvalidOperationException: "Session has not been configured for this application or request."

我在上面编辑了我的 ConfigureServices,在粘贴代码时,为了便于阅读,我删除了一些行,包括 AddDistributedMemoryCache 行,抱歉。会话在应用程序中运行,但显示的位置除外。

配置:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseSession();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

【问题讨论】:

  • 您是否将app.UseSession(); 包含在Configure 方法中?

标签: asp.net-core session dependency-injection httpcontext


【解决方案1】:

参考Session and app state in ASP.NET Core

要启用会话中间件,Startup 必须包含:

  • 任何IDistributedCache 内存缓存。 IDistributedCache 实现用作后备存储 会议。
  • ConfigureServices 中调用AddSession
  • Configure 中调用UseSession

还有

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {

    //... removed for brevity

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseSession(); // This must come before "UseMvc()"
    app.UseHttpContextItemsMiddleware();
    app.UseMvc();
}

中间件的顺序很重要。在前面的例子中,一个 当UseSessionInvalidOperationException 时发生异常 在UseMvc之后调用。
...
在调用UseSession 之前无法访问HttpContext.Session

【讨论】:

  • 感谢您的建议。我编辑了我的问题。
  • @Fritz IClaimsTransformation 在哪里使用?在中间件中。控制器或其他服务?
  • 根据link TransformAsync 将在每个 AuthenticateAsync 调用上运行,因此如果您的转换不是幂等的,则返回新的 ClaimsPrincipal 会更安全。
  • @Fritz 实际抛出的异常是什么。刚刚意识到它没有包含在 OP 中
  • System.InvalidOperationException:“尚未为此应用程序或请求配置会话。” (在 CustomClaimsTransformer 中最后发布的行中:var zz = _httpContextAccessor.HttpContext.Session;)
猜你喜欢
  • 2010-10-02
  • 2022-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-06
  • 2017-03-07
  • 1970-01-01
相关资源
最近更新 更多