【问题标题】:How do I inject dependency in owin startup class如何在 owin 启动类中注入依赖项
【发布时间】:2018-10-27 21:08:48
【问题描述】:

在我的 web api 应用程序中,我实现了 OAuth2。在 ApplicationOAuthProvider 的 GrantResourceOwnerCredentials 上,我正在调用我的自定义会员服务以登录并获取令牌。问题是我必须将会员服务注入 ApplicationOAuthProvider 才能使用该服务,但由于 owinStartup 类不允许它不' t 支持参数构造函数。如何在 GrantResourceOwnerCredentials 方法中注入/使用我的会员服务。

  public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
  {
      private readonly string _publicClientId;
      private readonly IMembershipService _membershipService;

      public ApplicationOAuthProvider(string publicClientId, 
           IMembershipService membershipService)
      {
        if (publicClientId == null)
        {
            throw new ArgumentNullException("publicClientId");
        }

        _publicClientId = publicClientId;
        this._membershipService = membershipService;
      }

      public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
      {
            AccountLogin LogCredentials = new AccountLogin();
            LogCredentials.UserName = context.UserName;
            LogCredentials.Password = context.Password;

            ProviderLoginResponse providerLoginResponse = 
                _membershipService.UserLogin(LogCredentials);
            if (providerLoginResponse.LoginStatus != "Y")
            {
                context.SetError("invalid_grant", "The user name or password 
                is incorrect.");
                return;
            }

            var claims = new List<Claim>()
            {
                    new Claim(ClaimTypes.Sid, Convert.ToString(1)),
                    new Claim(ClaimTypes.Name, providerLoginResponse.UserName),
                    new Claim(ClaimTypes.Email, providerLoginResponse.UserEmail)
            };

            ClaimsIdentity oAuthIdentity = new ClaimsIdentity(claims,
                    Startup.OAuthOptions.AuthenticationType);

            AuthenticationProperties properties = CreateProperties(context.UserName);

            AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);

            context.Validated(ticket);
      }
  }

我自己的创业班:

 public partial class Startup
 {
    private readonly IMembershipService _membershipService;

    //This will cause a runtime error owin startup class only support parameterless constructor
    public Startup(IMembershipService membershipService)
    {
        this._membershipService = membershipService;
    }

    public void ConfigureAuth(IAppBuilder app)
    {
          OAuthOptions = new OAuthAuthorizationServerOptions
          {
            TokenEndpointPath = new PathString("/Token"),

            //Here passing the _membershipService to ApplicationOAuthProvider constructor
            Provider = new ApplicationOAuthProvider(PublicClientId,_membershipService ),

            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            // In production mode set AllowInsecureHttp = false
            AllowInsecureHttp = true
          };
    }
 }

【问题讨论】:

  • @Marcus Höglund 我在我的项目中使用 autofac 我把 public static IContainer IoC { get;放; } 在启动类。 var builder = new ContainerBuilder(); builder.RegisterType() .As().InstancePerLifetimeScope(); var container = builder.Build(); Startup.IoC = 容器;但是 IContainer 没有任何解析方法 – Mussammil
  • 您可以将命名空间“Autofac.ResolutionExtensions”添加到具有 Resolve() 方法的启动类中。
  • @Marcus Höglund Autofac.ResolutionExtensions.Resolve 具有签名 public static TService Resolve(this IComponentContext context) ,所以我从哪里得到 IComponentContext。我无法在启动类中注入 IComponentContext 作为好
  • 在这里看看这个答案。在 ContainerBuilder 上调用 build 后,它会返回一个 IContainer。将其存储在 Startup.cs 中,然后在 stackoverflow.com/questions/6262704/… 上调用 Resolve

标签: asp.net-mvc asp.net-web-api dependency-injection oauth-2.0 owin


【解决方案1】:

一种解决方案是将依赖解析器作为静态变量存储在例如 Startup.cs 类中,然后针对该类解析接口。

当你用 MVC 标记这个问题时,我猜你有 Global.asax 文件以及 Startup.cs 类。 Global.asax 将在 Startup.cs 之前执行,我们可以在此解决方案中使用它。

在这个解决方案中,我使用 Unity 作为容器,但你可以使用任何你喜欢的东西。

在 Startup.cs 类中声明静态变量

public partial class Startup
{
    public static UnityContainer IoC { get; set; }

    ...

然后在 WebApiConfig.Register() 方法中,其中解析器附加到当前 HttpConfiguration,同时设置 Startup.cs 中的变量(注意这将在 Startup.cs 类之前调用​​)

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        var container = new UnityContainer();
        //register all your interfaces in the container
        container.RegisterType<IMembershipService, MembershipService>(new HierarchicalLifetimeManager());
        Startup.IoC = container;
        config.DependencyResolver = new UnityResolver(Startup.IoC);
    }
}

然后在你的 Startup.cs 中使用它

public partial class Startup
 {
    public static UnityContainer IoC { get; set; }

    public void ConfigureAuth(IAppBuilder app)
    {
          OAuthOptions = new OAuthAuthorizationServerOptions
          {
            TokenEndpointPath = new PathString("/Token"),

            //Resolve the interface here
            Provider = new ApplicationOAuthProvider(PublicClientId, Startup.IoC.Resolve<IMembershipService>() ),

            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            // In production mode set AllowInsecureHttp = false
            AllowInsecureHttp = true
          };
    }
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-07
    • 2015-11-11
    • 2016-06-25
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多