[英]Injected IPrincipal is anonymous but Web API Controller User object is authenticated
我正在编写Web API 2 / MVC5项目,我想要使用ASP.Net Identity对一些必须与IPrincipal一起工作的代码进行单元测试。 我没有依赖IPrincipal,而是想在我自己的IUserService后面抽象出来。 当我查看我注入的IUserService
, UserId
和UserName
为null。
public interface IUserService
{
string UserId { get; }
string UserName { get; }
}
使用的具体实现是:
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(); }
}
}
这是使用Ninject进行依赖注入。 在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);
}
如果我创建一个Func<IPrincipal>
和pass ()=>HttpContext.Current.User
一切正常。 但是,我没有看到任何人需要这样做,并且所有示例都表明了这种实现。
你有没有认证用户? 用户通过身份验证后,您需要负责创建IIdentity
和IPrincipal
。 然后,您需要使用IPrincipal
设置Thread.CurrentPrincipal
,并且还需要将IPrincipal
放在当前的HttpContext
。
为了使GenericIdentity
不被视为匿名, Name
属性必须是非空字符串。 为了使ClaimsIdentity
不被视为匿名, AuthenticationType
属性必须是非空的非空字符串。
所以,通常,您将执行以下操作:
// 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;
我确实看到你提到正在使用新的ASP.Net Identity模型。 因此,您肯定会在代码中使用ClaimsIdentity
和ClaimsPrincipal
。
这只是我的猜测,但这可能有问题:
kernel.Bind<IUserService>().To<UserService>().InRequestScope();
首先使用IUserService可以在设置HttpContext.Current.User
之前进行,因此,当前用户不会获得null
,因为在创建UserService
时, HttpContext.Current.User
为null
。 由于您定义了InRequestScope()
,因此在后续使用中提供了UserService
第一个创建对象,因此principal始终为null。
我可能会做的就是直接使用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(); }
}
}
如果要在桌面应用程序中使用IUserService
,请创建专用于桌面应用程序的实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.