自定义 UserManager 在 OAuthAuthorizationServerProvider 中不可用
Custom UserManager not available in OAuthAuthorizationServerProvider
我正在 WebApi 系统中实施 ASP.Net Identity 2。要管理新帐户的电子邮件确认,我必须创建一个自定义 ApplicationUserManager
并注册它以便为每个请求创建它:
public class IdentityConfig{
public static void Initialize(IAppBuilder app)
{
[snip]
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}
它在 ApiController 中正常工作,如下所示:
public class AccountController : ApiController
{
public ApplicationUserManager UserManager
{
get
{
return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
}
我面临的问题是,在我尝试在 OAuth 令牌创建方法中访问它之前,ApplicationUserManager.Create
方法没有被调用:
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var mgr = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
在上面的代码中,mgr 为空,因为 GetUserManager 检索到空
令牌创建方法是否以某种方式在管道中更早,以至于 CreatePerOwinContext
方法尚未被调用?如果是这样,缓存 ApplicationUserManager
以便它可以在 GrantResourceOwnerCredentials
内部使用的最佳方法是什么?
不要在 GrantResourceOwnerCredentials
中使用 HttpContext.Current.GetOwinContext()
,因为您已经有了上下文:(OAuthGrantResourceOwnerCredentialsContext context)
改为这样做:
var mgr = context.OwinContext.GetUserManager<ApplicationUserManager>();
CreatePerOwinContext
是为每个请求创建的,因此您应该能够获取对象 ApplicationUserManager
。
它应该在 Startup
处立即调用。也许您的启动实施不正确。
我写了一个答案 here,其中包含一些实施细节。
这个很棘手。事实证明,启动代码必须按照一定的顺序进行。
这段代码可以工作。
public class IdentityConfig{
public static void Initialize(IAppBuilder app)
{
// correct... first create DB context, then user manager, then register OAuth Provider
app.CreatePerOwinContext(AuthContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
如果更改在应用中注册代码的顺序,可能会产生意想不到的后果。此代码导致 ApplicationUserManager 在令牌生成方法 GrantResourceOwnerCredentials
中为 null
// wrong... these two lines must be after the ApplicationUserManager.Create line
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
[snip]
app.CreatePerOwinContext(AuthContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
虽然我正在做这件事,但还有另一件事可能会绊倒别人。这些行导致 AuthContext 在令牌生成方法 GrantResourceOwnerCredentials
中为 null
// wrong... The AuthContext must be instantiated before the ApplicationUserManager
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext(AuthContext.Create);
[snip]
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
如果 app.UseWebApi(config);
如果 app.UseWebApi(config);
行在 Oauth 设置之前。
以下将导致大多数调用 HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
到return null.
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config); <-- Bad location
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new ApplicationOAuthProvider("clientId"),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
app.UseOAuthBearerTokens(OAuthOptions);
将 app.UseWebApi(config);
移动到 app.UseOAuth 方法下方将允许您从 OwinContext 获取 ApplicationUserManager。
这对我有用:
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new ApplicationOAuthProvider("clientId"),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
app.UseOAuthBearerTokens(OAuthOptions);
app.UseWebApi(config); // <- Moved
我正在 WebApi 系统中实施 ASP.Net Identity 2。要管理新帐户的电子邮件确认,我必须创建一个自定义 ApplicationUserManager
并注册它以便为每个请求创建它:
public class IdentityConfig{
public static void Initialize(IAppBuilder app)
{
[snip]
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}
它在 ApiController 中正常工作,如下所示:
public class AccountController : ApiController
{
public ApplicationUserManager UserManager
{
get
{
return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
}
我面临的问题是,在我尝试在 OAuth 令牌创建方法中访问它之前,ApplicationUserManager.Create
方法没有被调用:
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var mgr = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
在上面的代码中,mgr 为空,因为 GetUserManager 检索到空
令牌创建方法是否以某种方式在管道中更早,以至于 CreatePerOwinContext
方法尚未被调用?如果是这样,缓存 ApplicationUserManager
以便它可以在 GrantResourceOwnerCredentials
内部使用的最佳方法是什么?
不要在 GrantResourceOwnerCredentials
中使用 HttpContext.Current.GetOwinContext()
,因为您已经有了上下文:(OAuthGrantResourceOwnerCredentialsContext context)
改为这样做:
var mgr = context.OwinContext.GetUserManager<ApplicationUserManager>();
CreatePerOwinContext
是为每个请求创建的,因此您应该能够获取对象 ApplicationUserManager
。
它应该在 Startup
处立即调用。也许您的启动实施不正确。
我写了一个答案 here,其中包含一些实施细节。
这个很棘手。事实证明,启动代码必须按照一定的顺序进行。
这段代码可以工作。
public class IdentityConfig{
public static void Initialize(IAppBuilder app)
{
// correct... first create DB context, then user manager, then register OAuth Provider
app.CreatePerOwinContext(AuthContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
如果更改在应用中注册代码的顺序,可能会产生意想不到的后果。此代码导致 ApplicationUserManager 在令牌生成方法 GrantResourceOwnerCredentials
中为 null// wrong... these two lines must be after the ApplicationUserManager.Create line
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
[snip]
app.CreatePerOwinContext(AuthContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
虽然我正在做这件事,但还有另一件事可能会绊倒别人。这些行导致 AuthContext 在令牌生成方法 GrantResourceOwnerCredentials
中为 null// wrong... The AuthContext must be instantiated before the ApplicationUserManager
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext(AuthContext.Create);
[snip]
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
如果 app.UseWebApi(config);
如果 app.UseWebApi(config);
行在 Oauth 设置之前。
以下将导致大多数调用 HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
到return null.
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config); <-- Bad location
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new ApplicationOAuthProvider("clientId"),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
app.UseOAuthBearerTokens(OAuthOptions);
将 app.UseWebApi(config);
移动到 app.UseOAuth 方法下方将允许您从 OwinContext 获取 ApplicationUserManager。
这对我有用:
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new ApplicationOAuthProvider("clientId"),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
app.UseOAuthBearerTokens(OAuthOptions);
app.UseWebApi(config); // <- Moved