我有一个Web Api 2 App,其中有两个都依赖于另一个类的类,并且我正在使用ninject来解决依赖关系。
public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
private IUserService _userService;
public AuthorizationServerProvider(IUserService userService)
{
_userService = userService;
}
}
public class RefreshTokenProvider : IAuthenticationTokenProvider
{
private IUserService _userService;
public RefreshTokenProvider(IUserService userService)
{
_userService = userService;
}
在startup.cs类中,我需要使用上述两个类,但是我当然不能在启动类中使用构造函数注入,因为该构造函数是在Ninject之前初始化的。
有什么方法可以解决,以便在ConfigureAuth方法中引用_tokenProvider和_authServerProvider?
public class Startup
{
private AuthorizationServerProvider _authServerProvider;
private RefreshTokenProvider _tokenProvider;
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
app.UseNinjectMiddleware(CreateKernel);
app.UseNinjectWebApi(config);
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
var oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true, //TODO: HTTPS
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = _authServerProvider,
RefreshTokenProvider = _tokenProvider
};
}
这是CreateKernel方法
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
这是我注册服务的地方
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<SimpleAuthorizationServerProvider>().ToSelf();
kernel.Bind<SimpleRefreshTokenProvider>().ToSelf();
}
我遵循ninject docs中的建议,但无济于事。
您正在以错误的方式进行操作。好吧,反正部分是错误的方式。您无法让OWIN将依赖项注入Startup类。因此,您将不得不使用配置了内核的内核app.UseNinjectMiddleware()
来解析您的选项配置类。我们将使用惰性内核来完成此操作。
首先,您应该在Startup.Auth.cs中进行配置。另外,您那里还有一些冗余。.app.UseNinjectWebApi(config)
将调用app.UseWebApi(config)
(请参阅参考资料)。我也不知道您为什么要在WebApiConfig.Register()
那里打电话,因为通常在Global.asax.cs中调用
无论如何,它应该看起来像这样(我没有测试过,但是应该很接近):
首先,我们将把您的内核创建转移到一个惰性方法,然后让您的UseNinjectMiddleware()
调用Startup.Configuration()
方法使用Startup类中的惰性内核作为成员。我认为这是最简单的lambda委托,而不是创建静态CreateKernel方法,效果最好。
public partial class Startup
{
private readonly Lazy<IKernel> _kernel = new Lazy<IKernel>(() =>
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
// here for brevity, move this to a RegisterServices or similar method,
//
kernel.Bind<IOAuthAuthorizationServerOptions>()
.To<MyOAuthAuthorizationServerOptions>();
kernel.Bind<IOAuthAuthorizationServerProvider>()
.To<AuthorizationServerProvider>();
kernel.Bind<IAuthenticationTokenProvider>().To<RefreshTokenProvider>();
kernel.Bind<IUserService>().To<MyUserService>();
return kernel;
});
public void Configuration(IAppBuilder app)
{
app.UseNinjectMiddleware(() => _kernel.Value);
var config = new HttpConfiguration();
app.UseNinjectWebApi(config);
ConfigureAuth(app);
}
}
然后在您的ConfigureAuth()中
public void ConfigureAuth(IAppBuilder app)
{
// .... other auth code
// Yes, boo hiss, service location, not much choice...
// Setup Authorization Server
app.UseOAuthAuthorizationServer(_kernel.Value
.Get<MyOAuthAuthorizationServerOptions>().GetOptions());
}
然后创建一个接口:
public interface IOAuthAuthorizationServerOptions
{
OAuthAuthorizationServerOptions GetOptions();
};
创建您的实现:
public class MyOAuthAuthorizationServerOptions : IOAuthAuthorizationServerOptions
{
private IOAuthAuthorizationServerProvider _provider;
private IAuthenticationTokenProvider _tokenProvider;
public MyOAuthAuthorizationServerOptions(IAuthenticationTokenProvider tProvider,
IOAuthAuthorizationServerProvider provider)
{
_provider = provider;
_tokenProvider = tProvider;
}
public OAuthAuthorizationServerOptions GetOptions()
{
return new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true, //TODO: HTTPS
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = _provider,
RefreshTokenProvider = _tokenProvider
};
}
}
编辑(15/4/6):
经过进一步的思考,我认为Lazy<T>
添加了一个确实不必要的附加参考。可以对其进行修改以更简洁的方式获得相同的结果,例如:
创建一个新的Startup.Ninject.cs类,并将其放在App_Start中:
public partial class Startup
{
public IKernel ConfigureNinject(IAppBuilder app)
{
var config = new HttpConfiguration();
var kernel = CreateKernel();
app.UseNinjectMiddleware(() => kernel)
.UseNinjectWebApi(config);
return kernel;
}
public IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
}
public class NinjectConfig : NinjectModule
{
public override void Load()
{
RegisterServices();
}
private void RegisterServices()
{
kernel.Bind<IOAuthAuthorizationServerOptions>()
.To<MyOAuthAuthorizationServerOptions>();
kernel.Bind<IOAuthAuthorizationServerProvider>()
.To<AuthorizationServerProvider>();
kernel.Bind<IAuthenticationTokenProvider>().To<RefreshTokenProvider>();
kernel.Bind<IUserService>().To<MyUserService>();
}
}
然后,在启动中执行以下操作:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var kernel = ConfigureNinject(app);
ConfigureAuth(app, kernel);
}
}
最后,修改ConfigureAuth以使用第二个参数,并改用它。
public void ConfigureAuth(IAppBuilder app, IKernel kernel)
{
// .... other auth code
// Yes, boo hiss, service location, not much choice...
// Setup Authorization Server
app.UseOAuthAuthorizationServer(
kernel.Get<MyOAuthAuthorizationServerOptions>().GetOptions());
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句