dependency-injection - OAuthAuthorizationServerProvider 实现中的 Autofac 依赖注入(inject)

标签 dependency-injection autofac owin asp.net-web-api2 bearer-token

我正在创建一个 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' 的问题。来自 OwinContextOAuthAuthorizationServerProvider类并从中解决服务依赖关系,而不是让 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/

相关文章:

java - Spring Quartz 使用父类构造函数设置基于构造函数的注入(inject)

c# - 具有依赖注入(inject)的 MVC 6 自定义模型绑定(bind)器

c# - 解决实现相同接口(interface)的泛型类型时的 Autofac 问题,需要 Resolve() 两次或更多次

.net - 将 Windows 身份验证与 OAuth 2.0 结合使用

c# - Autofac:如何加载引用但未直接使用的程序集

java - 将 AppContext 实现为 Play 插件

Angular:在 AoT 中提供 Http

c# - 为什么我的继承类没有隐藏我的基类方法?

asp.net-web-api - 用 OWIN 中间件异常处理程序替换 Web Api 2.2 中的 IExceptionHandler

authentication - 使用 ExternalLoginCallback 进行身份验证如何获取 UserId 和 UserName ASP.NET MVC5