How do I inject dependency in owin startup class

回眸只為那壹抹淺笑 提交于 2019-12-24 00:42:18

问题


In my web api application I implemented OAuth2. On GrantResourceOwnerCredentials of ApplicationOAuthProvider I am calling my custom membership service to login and get the token.The problem is I have to inject the membership service into ApplicationOAuthProvider in order to use the service but it didn't allow it due to owinStartup class which don't support the parameter constructor.How do I inject/use my membership service in GrantResourceOwnerCredentials method.

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

My owin startup class :

 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:


One solution is to store the dependecy resolver as a static variable in, for example, the Startup.cs class and then resolve the interface against that.

As you tagged this question with MVC I'm guessing you have the Global.asax file along with the Startup.cs class. The Global.asax will be executed before the Startup.cs and that we can use in this solution.

In this solution I use Unity as container but you could use what ever you like.

Declare the static variable in Startup.cs class

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

    ...

Then in the WebApiConfig.Register() method, where the resolver is attached to the current HttpConfiguration, also set the variable in Startup.cs (Note that this will be called before the Startup.cs class)

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

Then use it in your 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
          };
    }
 }


来源:https://stackoverflow.com/questions/48335538/how-do-i-inject-dependency-in-owin-startup-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!