简体   繁体   English

注入的IPrincipal是匿名的,但Web API Controller User对象已通过身份验证

[英]Injected IPrincipal is anonymous but Web API Controller User object is authenticated

I'm writing a Web API 2/MVC5 project and I wanted to unit test some code that had to work with an IPrincipal using ASP.Net Identity. 我正在编写Web API 2 / MVC5项目,我想要使用ASP.Net Identity对一些必须与IPrincipal一起工作的代码进行单元测试。 Instead of relying on IPrincipal I wanted to abstract that behind my own IUserService. 我没有依赖IPrincipal,而是想在我自己的IUserService后面抽象出来。 When I look at my injected IUserService the UserId and UserName are null. 当我查看我注入的IUserServiceUserIdUserName为null。

public interface IUserService
{
    string UserId { get;  }
    string UserName { get;  }
}

The concrete implementation being used is: 使用的具体实现是:

public class UserService : IUserService
{
    private IPrincipal _principal;

    public UserService(IPrincipal principal)
    {
        _principal = principal;
    }

    public string UserName
    {
        get { return _principal.Identity.GetUserName(); }

    }

    public string UserId
    {
        get { return _principal.Identity.GetUserId(); }

    }
}

This is using Ninject for dependency injection. 这是使用Ninject进行依赖注入。 Inside NinjectWebCommon.cs I have: 在NinjectWebCommon.cs里面,我有:

private static void RegisterServices(IKernel kernel)
{
   kernel.Bind<IBooksService>().To<BooksService>().InRequestScope();
   kernel.Bind<DbContext>().To<ApplicationDbContext>().InRequestScope();
   kernel.Bind<ApplicationDbContext>().To<ApplicationDbContext>().InRequestScope();
   kernel.Bind<IUserStore<ApplicationUser>>().To<UserStore<ApplicationUser>>().InRequestScope();
   kernel.Bind<UserManager<ApplicationUser>>().To<UserManager<ApplicationUser>>().InRequestScope();
   kernel.Bind<IBookRepository>().To<BookRepository>().InRequestScope();
   kernel.Bind<IUserService>().To<UserService>().InRequestScope();
   kernel.Bind<IPrincipal>().ToMethod(ctx => HttpContext.Current.User);
}

If I create a Func<IPrincipal> and pass ()=>HttpContext.Current.User everything works fine. 如果我创建一个Func<IPrincipal>和pass ()=>HttpContext.Current.User一切正常。 However, I don't see anyone needing to do this and all of the examples suggest this implementation. 但是,我没有看到任何人需要这样做,并且所有示例都表明了这种实现。

Do you ever authenticate the user? 你有没有认证用户? Once the user is authenticated, you need to take care of creating an IIdentity and an IPrincipal . 用户通过身份验证后,您需要负责创建IIdentityIPrincipal Then, you need to set Thread.CurrentPrincipal with the IPrincipal , and you also need to put the IPrincipal in the current HttpContext . 然后,您需要使用IPrincipal设置Thread.CurrentPrincipal ,并且还需要将IPrincipal放在当前的HttpContext

In order for a GenericIdentity to not be considered anonymous, the Name property must be a non-empty string. 为了使GenericIdentity不被视为匿名, Name属性必须是非空字符串。 In order for a ClaimsIdentity to not be considered anonymous, the AuthenticationType property must be a non-null, non-empty string. 为了使ClaimsIdentity不被视为匿名, AuthenticationType属性必须是非空的非空字符串。

So, generally, you'll do the following: 所以,通常,您将执行以下操作:

// Perform authentication, usually using some kind of AuthenticationFilter or
// AuthorizationFilter.
// After authenticating, and still within the Auth*Filter,

// I'm going to use a GenericIdentity, but this can be converted to a 
// ClaimsIdentity if you're using the default Name claim.
IIdentity identity = new GenericIdentity("myUserName", "myAuthenticationType");

// Again, you could use a ClaimsPrincipal, the concept, however, is the same.
IPrincipal principal = new GenericPrincipal(identity, null /* no roles */);
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = principal;

I did see that you mentioned the new ASP.Net Identity model is being used. 我确实看到你提到正在使用新的ASP.Net Identity模型。 So you'd definitely use ClaimsIdentity and ClaimsPrincipal in your code. 因此,您肯定会在代码中使用ClaimsIdentityClaimsPrincipal

This is only my guess, but this may be faulty: 这只是我的猜测,但这可能有问题:

kernel.Bind<IUserService>().To<UserService>().InRequestScope();

First use of IUserService can occur before HttpContext.Current.User is set, so instead of current user, you get null , because at the moment UserService was created, HttpContext.Current.User was null . 首先使用IUserService可以在设置HttpContext.Current.User之前进行,因此,当前用户不会获得null ,因为在创建UserService时, HttpContext.Current.Usernull Since you have InRequestScope() defined, first created object of UserService is provided in subsequent uses, so principal is null all the time. 由于您定义了InRequestScope() ,因此在后续使用中提供了UserService第一个创建对象,因此principal始终为null。

What I would probably do is just use HttpContext directly: 我可能会做的就是直接使用HttpContext

public class HttpContextBasedUserService : IUserService
{
    public string UserName
    {
        get { return HttpContext.Current.User.Identity.GetUserName(); }

    }

    public string UserId
    {
        get { return HttpContext.Current.User.Identity.GetUserId(); }

    }
}

If you want to use IUserService in desktop application, create implementation dedicated for desktop use. 如果要在桌面应用程序中使用IUserService ,请创建专用于桌面应用程序的实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 控制器中没有IPrincipal用户信息 - No IPrincipal user information in controller 经过身份验证的用户在 web api owin 中间件中丢失 - Authenticated user is lost in web api owin middleware 用户(IPrincipal)在ApiController的构造函数上不可用,使用Web Api 2.1和Owin - User (IPrincipal) not available on ApiController's constructor using Web Api 2.1 and Owin 如何在Web API 2中检查用户是否已通过身份验证 - How to check if user is authenticated in Web API 2 用户通过身份验证时调用Web Api方法 - Calling a Web Api method when user is authenticated 通过身份验证时从web api控制器操作返回图像 - Return image from web api controller action while authenticated 具有IPrincipal集的单元测试ASP.net Web API - Unit testing ASP.net Web API with IPrincipal set 在 .NET 5 Web API 中动态连接到多个数据库(取决于经过身份验证的用户) - Connecting to multiple databases, dynamically (depending on the authenticated user) in an .NET 5 Web API 从.Net Web API中经过Azure身份验证的AD获取用户名 - Get user name from Azure authenticated AD in .Net Web API Web API没有会话 - 需要检查用户是否经过身份验证 - Web API has no session - need to check if user is authenticated
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM