我正在创建一个 Web Api 应用程序,并且我想使用不记名 token 进行用户身份验证。
我实现了 token 逻辑,遵循 this post一切似乎都很好。
注意:我没有使用 ASP.NET 身份提供程序。相反,我为它创建了一个自定义用户实体和服务。
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var config = new HttpConfiguration();
var container = DependancyConfig.Register();
var dependencyResolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = dependencyResolver;
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
var oAuthServerOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
这是我对 SimpleAuthorizationServerProvider 类的实现
private IUserService _userService;
public IUserService UserService
{
get { return (IUserService)(_userService ?? GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUserService))); }
set { _userService = value; }
}
public async override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
var user = await UserService.GetUserByEmailAndPassword(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
调用/token url 后,我收到以下错误
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself
有没有办法在这个类中使用依赖注入(inject)?我正在使用存储库模式来访问我的实体,因此我认为创建对象上下文的新实例不是一个好主意。这样做的正确方法是什么?
最佳答案
我有一个类似的问题。
这里的问题是当你尝试注入(inject) IUserService
在您的提供商中,Autofac 检测到它已注册为 InstancePerRequest
(使用众所周知的生命周期标签 'AutofacWebRequest'
)但是 SimpleAuthorizationServerProvider
注册于 'root'
'AutofacWebRequest'
所在的容器范围范围不可见。
建议的解决方案是将依赖项注册为 InstancePerLifetimeScope
.这显然解决了问题,但引入了新问题。所有依赖项都在 'root'
中注册范围,这意味着具有相同的 DbContext
和所有请求的服务实例。 Steven在这个answer 中解释得很好为什么分享 DbContext
不是一个好主意?请求之间。
经过更深入的调查任务,我已经解决了获取 'AutofacWebRequest'
的问题。来自 OwinContext
在 OAuthAuthorizationServerProvider
类并从中解决服务依赖关系,而不是让 Autofac 自动注入(inject)它们。为此,我使用了 OwinContextExtensions.GetAutofacLifetimeScope()
来自 Autofac.Integration.Owin
的扩展方法,请参见下面的示例:
using Autofac.Integration.Owin;
...
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
...
// autofacLifetimeScope is 'AutofacWebRequest'
var autofacLifetimeScope = OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);
var userService = autofacLifetimeScope.Resolve<IUserService>();
...
}
我做了
OAuthAuthorizationServerProvider
注册和内注ConfigureOAuth
方法与 Laurentiu Stamate 提出的方法相似在 another response对于这个问题,如 SingleInstance()
.我已经实现了
RefreshTokenProvider
以同样的方式。编辑
@BramVandenbussche,这是我的
Configuration
Startup
中的方法类,您可以在其中看到添加到 OWIN 管道的中间件的顺序:public void Configuration(IAppBuilder app)
{
// Configure Autofac
var container = ConfigureAutofac(app);
// Configure CORS
ConfigureCors(app);
// Configure Auth
ConfigureAuth(app, container);
// Configure Web Api
ConfigureWebApi(app, container);
}
关于dependency-injection - OAuthAuthorizationServerProvider 实现中的 Autofac 依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25871392/