Asp.net Identity,生成WebApi令牌OAuthGrantResourceOwnerCredentialsContext - 无法使用Unity访问UserManager

时间:2014-11-20 13:44:49

标签: asp.net-web-api unity-container asp.net-identity asp.net-web-api2 constructor-injection

我正在尝试设置项目结构,以便我有一个WebApi,WebUI和Domain层。我已将所有Asp.Net.Identity对象移动到Domain层中,并且也在此处设置了ApplicationContext(继承自IdentityContext)。

(我已经将本教程和软件包用作非常好的基础。http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/

在WebAPI层中,我可以正确使用帐户控制器登录和注册。但是,我无法生成访问令牌。

OAuthGrantResourceOwnerCredentialsContext方法在内部使用

var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

这样工作正常,但并没有给我与我的帐户控制器相同的上下文,因为我在此使用Unity构造函数注入来使用域中的ApplicationUserManager。

我尝试过注入OAuth类,但我似乎从来没有得到实例。

有什么建议吗?


编辑,这是我在默认WebApi项目中的Startup类中所拥有的。

// Configure the application for OAuth based flow
        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        };

因此,在获取访问令牌时似乎使用了ApplicationOAuthProvider。

- 更多信息。

UnityConfig.cs

container.RegisterType<ApplicationDbContext>(); //this is referencing my domain layer

Startup.Auth.cs

app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());

// Configure the application for OAuth based flow
        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        };

ApplicationOAuthProvider.cs

注入构造函数如下

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
    private readonly string _publicClientId;

    private ApplicationUserManager userManager;

    public ApplicationOAuthProvider(ApplicationUserManager userManager)
    {
        this.userManager = userManager;
    }

    public ApplicationOAuthProvider(string publicClientId)
    {

        //this.userManager = userManager;

        if (publicClientId == null)
        {
            throw new ArgumentNullException("publicClientId");
        }

        _publicClientId = publicClientId;
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        //var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); //PROBLEM LINE!!!

        ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
    }
}

问题行如上所示。请求令牌时调用此方法,userManager始终为null。


编辑以显示UnityWebApiActivator.cs

public static class UnityWebApiActivator
{
    /// <summary>Integrates Unity when the application starts.</summary>
    public static void Start() 
    {
        // Use UnityHierarchicalDependencyResolver if you want to use a new child container for each IHttpController resolution.
        // var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.GetConfiguredContainer());
        var resolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());

        GlobalConfiguration.Configuration.DependencyResolver = resolver;
    }

    /// <summary>Disposes the Unity container when the application is shut down.</summary>
    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}

1 个答案:

答案 0 :(得分:0)

我刚刚使用Identity创建了纯WebApi项目,检查了类并且不确定我是否正确理解了您的问题。

标准VS2013模板在Startup.Auth.cs

中包含此内容
public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        // blah - other stuff

        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            Provider = new ApplicationOAuthProvider(PublicClientId),
            // another blah
        };

        app.UseOAuthBearerTokens(OAuthOptions);

        //blah-blah-blah
    }
}

我已经检查过,ApplicationOAuthProvider在其他任何地方都没有使用过。所以不需要注射它。

正如你所说,在这个类的内部,它要求context.OwinContext.GetUserManager<ApplicationUserManager>()获得用户管理器。如果在那里得到ApplicationDbContext的错误实例,则会将不正确的ApplicationUserManager实例注入到Owin上下文中。你还有这句话:

app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

用这个替换它:

app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());

这应该做的 - 这将是最好的解决方案。

或者在ApplicationOAuthProvider替换行中,从OWIN上下文中获取ApplicationUserManager

var userManager = DependencyResolver.Current.GetService<ApplicationUserManager>()

这应该从Unity解析您的用户经理,为您提供正确的DbContext