CustomClaimsTransformer中的IHttpContextAccessor会话无效操作异常

时间:2018-08-30 10:30:41

标签: .net session dependency-injection core httpcontext

我跟随官方文档从CustomClaimsTransformer中的自定义组件访问HttpContext。 背景知识,我以前有一个.net核心Web应用程序,在该应用程序中,我使用该会话使管理员能够使用其他用户的视图(身份)跳入该应用程序(出于支持目的)。我存储信息,应在Session中为该用户准备视图。现在,我想使其更加优雅,并使用基于声明和基于角色的授权的.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."

我们非常感谢您的帮助

编辑1:

我在上面的代码中编辑了我的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?}");
        });
    }

1 个答案:

答案 0 :(得分:0)

引用Session and app state in ASP.NET Core

  

要启用会话中间件,public class BackUpFolder { public void copy(File sourceLocation, File targetLocation) throws IOException { if (sourceLocation.isDirectory()) { copyDirectory(sourceLocation, targetLocation); } else { copyFile(sourceLocation, targetLocation); } } private void copyDirectory(File source, File target) throws IOException { if (!target.exists()) { target.mkdir(); } for (String f : source.list()) { copy(new File(source, f), new File(target, f)); } } private void copyFile(File source, File target) throws IOException { try ( InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(target)) { byte[] buf = new byte[1024]; int length; while ((length = in.read(buf)) > 0) { out.write(buf, 0, length); } } } public static void main(String[] args) { try { BackUpFolder backUpFolder = new BackUpFolder(); String location = "./src/edu/abc/locationFiles/daofile"; //File path you are getting from file chooser String target = "./src"; //target place you want to patse File locFile = new File(location); File tarFile = new File(target); backUpFolder.copyDirectory(locFile, tarFile); } catch (IOException ex) { Logger.getLogger(BackUpFolder.class.getName()).log(Level.SEVERE, null, ex); } } } 必须包含:

     
      
  • 任何Startup内存缓存。 IDistributedCache实现用作以下项的后备存储   会议。
  •   
  • 调用IDistributedCache中的AddSession
  •   
  • 调用ConfigureServices中的UseSession
  •   

Configure
  

中间件的顺序很重要。在前面的示例中,   当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(); } InvalidOperationException时发生UseSession例外   在UseMvc之后调用。
  ...
  在调用HttpContext.Session之前无法访问UseSession