我实现了令牌逻辑,跟随着 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); } }
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
有没有办法在这个类中使用依赖注入?我正在使用存储库模式来访问我的实体,所以我不认为创建对象上下文的新实例是个好主意.这样做的正确方法是什么?
这里的问题是,当您尝试在提供程序中注入IUserService时,Autofac检测到它已注册为InstancePerRequest(使用公知的生命周期范围标记“AutofacWebRequest”),但SimpleAuthorizationServerProvider注册在“根”容器范围内其中“AutofacWebRequest”范围不可见.
一个提出的解决方案是将依赖项注册为InstancePerLifetimeScope.这显然解决了这个问题,但是引入了新的问题.所有依赖项都注册在“根”范围内,这意味着对所有请求都具有相同的DbContext和服务实例. Steven在这个answer中解释非常好,为什么不是在请求之间共享DbContext的好主意.
在深入调查任务之后,我已经解决了在OAuthAuthorizationServerProvider类中从OwinContext获取“AutofacWebRequest”的问题,并解决了它的服务依赖关系,而不是让Autofac自动注入它们.为此,我使用了Autofac.Integration.Owin中的OwinContextExtensions.GetAutofacLifetimeScope()扩展方法,请参见下面的示例:
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方法中,类似于another response Laurentiu Stamate提出的与SingleInstance()相关的问题.
我以同样的方式实现了RefreshTokenProvider.
编辑
@BramVandenbussche,这是我在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); }