使用AutoFac将BL注入OAuth

问题描述 投票:1回答:1

我已遵循此Blog在WebApi中生成刷新令牌。在RefreshTokenProvider类中,他正在访问AuthenticationRepository以在表中为生成的刷新令牌创建一行。每件事都完美无缺。但是现在我想将依赖注入添加到我的WebAPI项目中。对于依赖项注入,我使用具有以下配置的AutoFac

public class IocConfig
{
    public static AutofacWebApiDependencyResolver Configure()
    {
        var builder = new ContainerBuilder();
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        builder.RegisterType<DefaultPrincipalProvider>().As<IPrincipalProvider>();
        builder.RegisterType<Logic>().AsSelf().InstancePerRequest();
        builder.RegisterType<DataAccess>().AsSelf().InstancePerRequest();
        builder.RegisterType<AuthRefreshTokenProvider>().As<IAuthenticationTokenProvider>().SingleInstance();
        var container = builder.Build();
        var resolver = new AutofacWebApiDependencyResolver(container);
        GlobalConfiguration.Configuration.DependencyResolver = resolver;
        return resolver;
    }
}

Global.asax.cs

protected void Application_Start()
{
    IocConfig.Configure();
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

Controller

public class ItemController : ApiController
{
    private Logic _logic;
    public ItemController(Logic logic)
    {
        _logic = logic;
    }
}

业务逻辑

public partial class Logic
{
    IPrincipalProvider _principalProvider;
    DataAccess _dataAccess;
    string _currentUserId;

    public Logic(DataAccess dataAccess,IPrincipalProvider provider)
    {
        _dataAccess = dataAccess;
    }

}

DataAccess

public partial class DataAccess
{

    public DataAccess()
    {
    }

}

上面的配置都可以正常工作,但是我对如何配置OAuthAuthorizationServerOptions感到困惑。我需要将BusinessLogic实例传递给AuthRefreshTokenProvider。

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    RefreshTokenProvider = new AuthRefreshTokenProvider(),// Need To use Dependency Injection Here
    // In production mode set AllowInsecureHttp = false
    AllowInsecureHttp = true
};

AuthRefreshTokenProvider

public class AuthRefreshTokenProvider : IAuthenticationTokenProvider
{
    private Logic _logic;
    public AuthRefreshTokenProvider(Logic logic)
    {
        _logic = logic;
    }
}

我已经尝试了很多方法来完成这项工作。我知道问题出在SingleInstance的实例化InstancePerRequest()中。我一直在阅读很多文章和stackoverflow帖子,以使它正常工作,但似乎无法使其工作]

c# asp.net-web-api dependency-injection owin autofac
1个回答
1
投票
假设您的应用程序是ASP.Net WebAPI(不是Core),则需要捕获HttpRequestMessage才能访问请求范围。

首先,您需要在某个地方保留请求消息,并且由于您想从单例服务访问请求消息,因此新服务也必须是

singleton服务:

interface IHttpRequestAccessor { HttpRequestMessage Request { get; set; } } class HttpRequestAccessor : IHttpRequestAccessor { private readonly AsyncLocal<HttpRequestMessageHolder> _currentRequest = new AsyncLocal<HttpRequestMessageHolder>(); public HttpRequestMessage Request { get => _currentRequest.Value?.Value; set { HttpRequestMessageHolder holder = _currentRequest.Value; if (holder != null) { holder.Value = null; } if (value != null) { _currentRequest.Value = new HttpRequestMessageHolder { Value = value }; } } } private class HttpRequestMessageHolder { public HttpRequestMessage Value { get; set; } } } builder.RegisterType<HttpRequestAccessor>() .As<IHttpRequestAccessor>() .SingleInstance();

这是如何工作的?

此类公开一个属性,以获取并将HttpRequestMessage设置为当前异步执行上下文。由于每个请求的数据上下文都不相同,并且在WebAPI请求管道的所有步骤中都继承,因此我们可以将其放在一个位置,然后在另一个位置用于同一HTTP请求。这与在ASP.Net Core应用中完成IHttpContextAccessor的概念相同。

现在我们需要在某个地方捕获并设置IHttpRequestAccessor.Requestdelegating handler是一个不错的选择:

class CaptureHttpRequestMessageHandler : DelegatingHandler { private readonly IHttpRequestAccessor _requestMessageAccessor; public CaptureHttpRequestMessageHandler(IHttpRequestAccessor requestMessageAccessor) { _requestMessageAccessor = requestMessageAccessor; } protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (_requestMessageAccessor != null) { _requestMessageAccessor.Request = request; } return base.SendAsync(request, cancellationToken); } }

并将其添加到配置中:

GlobalConfiguration.Configuration.MessageHandlers.Add(
    new CaptureHttpRequestMessageHandler(/* resolve services here */));

毕竟,将IHttpRequestAccessor注入您的AuthRefreshTokenProvider并删除Logic

[需要Logic时,使用以下命令即时解决:

_httpRequestAccessor.Request.GetDependencyScope().GetService(typeof(Logic));

只要在HTTP请求中[[0]时调用AuthRefreshTokenProvider,它就应该起作用。

© www.soinside.com 2019 - 2024. All rights reserved.