C# Thread.CurrentPrincipal Identity.Name在asp.net mvc 6(vNext)中为空

C# Thread.CurrentPrincipal Identity.Name在asp.net mvc 6(vNext)中为空,c#,asp.net-mvc,asp.net-core,asp.net-core-mvc,C#,Asp.net Mvc,Asp.net Core,Asp.net Core Mvc,我正在使用Asp.NETMVC6(vNext),Identity 3.0.*beta3开发一个web应用程序。这是一个具有UI、服务和数据库的三层应用程序。我可以使用Asp.net标识的SignInManager类登录用户,并尝试检索服务层中角色和声明的用户详细信息,以便验证用户是否有权执行某些操作 如何从服务层中的当前请求主体标识获取当前用户名。在MVC5中,我使用了Thread.CurrentPrincipal来实现这一点。但是在MVC6中,Thread.CurrentPrincipal的I

我正在使用Asp.NETMVC6(vNext),Identity 3.0.*beta3开发一个web应用程序。这是一个具有UI、服务和数据库的三层应用程序。我可以使用Asp.net标识的
SignInManager
类登录用户,并尝试检索服务层中角色和声明的用户详细信息,以便验证用户是否有权执行某些操作

如何从服务层中的当前请求主体标识获取当前用户名。在MVC5中,我使用了
Thread.CurrentPrincipal
来实现这一点。但是在MVC6中,
Thread.CurrentPrincipal
的Identity.Name设置为null


有人能告诉我怎么做吗?另外,如果您有更好的解决方案,请告诉我。

可能有更好的方法。但现在,我正在添加一个自定义中间件,如下面的代码所示,以便在startup.cs类的当前线程中注入ussername。在服务层,我将使用Thread.GetData(Thread.getnamedataslot(“当前用户名”))读取它


假设您可以在您的层中传递access服务,相当于HttpContext.Current,它是托管层公开的服务。

如果您在Startup.cs中调用了
AddIdentity()
,或者在任何配置依赖项注入的地方,它将自动注册一个singleton
HttpContextAccessor
以满足
IHttpContextAccessor
服务

此时,在您的服务层中,您可以插入
IHttpContextAccessor
并从中检索上下文。这假设您了解依赖项注入系统的工作原理,并使用它来实例化服务层类,而不仅仅是
new
ing它们

如果您希望能够方便地访问
HttpContext
中公开的
ClaimsPrincipal
Id
Name
,请确保导入
System.Security.Claims
,以便访问为您提供
GetUserName()
GetUserId>的扩展()
扩展方法


(这是自VS2015 RC1发布的
beta4
软件包以来的最新版本)

我知道HttpApplication对象在获取线程时将线程的主体设置为HttpContext的主体。您是否尝试过HttpContext.Current.User,也为null?@RazvanDumitru感谢您的回复。您能告诉我如何在服务层中获取HttpContext吗?ASP.Net 5的编写方式是完全可单元测试的,只有很少的静态p尽可能多的属性。因此,用户的主体等值应该作为参数传递到服务层中。(这不是一个真正的答案,而是一个遵循公认设计模式的建议。)此外,由于
async
的方式正在改变,线程特定的信息可能会丢失。@MattDeKrey是对的。您应该始终传递上下文数据和用户信息数据(尤其是)以及您需要将其作为参数发送到服务层的所有值。编写您自己的安全相关代码充满了危险。例如,在这里,如果经过身份验证的用户发出请求,它们将最终进入线程槽。如果未经身份验证的用户发出请求,并且该请求发生在同一线程上,您不会清除用户名,因此它们将被删除直到作为第一个用户进行身份验证==您刚刚打开了被黑客攻击的大门。如果(!httpContext.user.Identity.IsAuthenticated)然后…清除线程身份验证插槽Hanks Jon。实际上,我在服务层读取该插槽后正在清除该插槽。我每个请求只需要一次用户名。但是您提出了一个好的建议。我希望有更好的方法来做到这一点。此外,直接使用线程静态数据会在您开始使用asyn时导致悲伤c方法。通过让服务层直接访问线程本地数据,而不是声明对可以模拟的IHttpContextAccessor的依赖关系,您现在也让服务层更难测试。我甚至建议您进一步,完全从代码中删除任何与
HttpContext
相关的内容,因为您真正想要的是提供当前
ClaimsPrincipal
的服务。制作一个
iccurrentclaimsprincipal
接口,公开一个
CurrentPrincipal
属性。创建一个实现该属性的类,该类使用
IHttpContextAccessor
依赖项读取并返回当前主体从
CurrentPrincipal
属性。
public class Startup {

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
    {

        //.... code

        app.UseIdentity();

        //... more code

        app.Use(async (ctx, next) =>
        {
            var httpContext = (ctx as HttpContext);
            if (httpContext.User.Identity.IsAuthenticated)
            {
                Thread.SetData(Thread.GetNamedDataSlot("current-username"), httpContext.User.Identity.Name);
            }
            await next();
        });

        //... more code

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

    }
}