簡體   English   中英

注入的IPrincipal是匿名的,但Web API Controller User對象已通過身份驗證

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

我正在編寫Web API 2 / MVC5項目,我想要使用ASP.Net Identity對一些必須與IPrincipal一起工作的代碼進行單元測試。 我沒有依賴IPrincipal,而是想在我自己的IUserService后面抽象出來。 當我查看我注入的IUserServiceUserIdUserName為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一切正常。 但是,我沒有看到任何人需要這樣做,並且所有示例都表明了這種實現。

你有沒有認證用戶? 用戶通過身份驗證后,您需要負責創建IIdentityIPrincipal 然后,您需要使用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模型。 因此,您肯定會在代碼中使用ClaimsIdentityClaimsPrincipal

這只是我的猜測,但這可能有問題:

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

首先使用IUserService可以在設置HttpContext.Current.User之前進行,因此,當前用戶不會獲得null ,因為在創建UserService時, HttpContext.Current.Usernull 由於您定義了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM