我正在尝试设置一个项目结构,以便我有一个WebApi,WebUI和域层。我已经将所有Asp.Net.Identity对象移动到域层,并且还在这里设置了ApplicationContext(继承自IdentityContext)。
(我使用本教程和软件包作为基础,非常好 http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/。
在WebAPI层中,我能够正确使用帐户控制器进行登录和注册。但是,我无法生成访问令牌。
OAuthGrantResourceOwnerCredentialsContext 方法在内部使用
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
这工作正常,但不能为我提供与我的帐户控制器相同的上下文,因为我在其中使用 Unity 构造函数注入来使用域中的应用程序用户管理器。
我尝试注入 OAuth 类,但我似乎从未恢复实例。
有什么建议吗?
编辑,这是我在默认 WebApi 项目的启动类中拥有的内容。
// 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
};
因此,在获取访问令牌时似乎使用了应用程序OAuth提供程序。
--更多信息。
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);
}
}
问题行如上所示。此方法在请求令牌时被调用,并且用户管理器始终为 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();
}
}
我刚刚使用 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
。