如何在owin启动类中注入依赖项

时间:2018-01-19 06:47:17

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

在我的web api应用程序中,我实现了OAuth2。在ApplicationOAuthProvider的GrantResourceOwnerCredentials上,我正在调用我的自定义成员资格服务来登录并获取令牌。问题是我必须将成员资格服务注入ApplicationOAuthProvider才能使用该服务,但由于owinStartup类它没有允许它不支持参数构造函数。如何在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);
      }
  }

我的owin启动课程:

 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
          };
    }
 }

1 个答案:

答案 0 :(得分:5)

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

当你用MVC标记这个问题时,我猜你有Full.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
          };
    }
 }