gpt4 book ai didi

c# - 依赖注入(inject)(使用 SimpleInjector)和 OAuthAuthorizationServerProvider

转载 作者:IT王子 更新时间:2023-10-29 04:53:12 25 4
gpt4 key购买 nike

依赖注入(inject)的新手,所以这可能是一件简单的事情,但我已经尝试过但无法弄清楚,我正在使用简单注入(inject)器。

我有一个使用 SimpleInjector 的 WebApi 非常好,现在我想使用 OAuth 实现安全性。

为此,我开始遵循本教程,它非常有帮助,但没有使用依赖注入(inject)

http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/

我的 global.asax 文件看起来像这样,用于设置依赖注入(inject)(工作完美)

protected void Application_Start()
{
SimpleInjectorConfig.Register();

GlobalConfiguration.Configure(WebApiConfig.Register);
}

我已经创建了一个 Startup.Auth.cs 文件来配置 OAuth

public class Startup
{
public void Configuration(IAppBuilder app)
{
var OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new MyAuthorizationServerProvider() // here is the problem
};

// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}

正如我在上面评论的那样,MyAuthorizationServerProvider 是问题所在。它需要一个我通常注入(inject)的 IUserService 参数。我不想清空构造函数,因为我的 IUserService 也注入(inject)了一个存储库。这是文件

public class ApiAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
private IUserService _service;
public ApiAuthorizationServerProvider (IUserService service)
{
_service = service;
}

public override async Task ValidateClientAuthentication(
OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}

public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin",
new[] { "*" });

IUserService service = Startup.Container.GetInstance<IUserService>();
User user = _service.Query(e => e.Email.Equals(context.UserName) &&
e.Password.Equals(context.Password)).FirstOrDefault();

if (user == null)
{
context.SetError("invalid_grant",
"The user name or password is incorrect.");
return;
}

var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));

context.Validated(identity);

}
}

我怎样才能使它与依赖注入(inject)一起工作?这种情况肯定经常发生,并且必须能够做一些事情来处理它。我确信这很简单,但我仍在学习。

最佳答案

我花了一些时间来确定是否可以直接使用 app.Use() 方法而不是 在 Owin 管道中注册 OAuthAuthorizationServerOptions >app.UseOAuthAuthorizationServer() 这只是 app.Use() 的扩展方法。 app.Use() 有一个重载,您可以在其中注册一个委托(delegate),您可以使用它来构造 OAuthAuthorizationServerOptions

不幸的是,这项工作进入了死胡同,因为看起来即使我们使用委托(delegate)来构造,Owin 管道也很可能只会调用一次,这会导致相同的结果,即单例实例OAuthAuthorizationServerOptions 的,因此该类的所有依赖项也将是单例。

因此,保持一切正常运行的唯一解决方案是,每次调用 GrantResourceOwnerCredentials() 方法时,都拉取一个新的 UserService 实例。

但要遵循Simple Injector design principlesApiAuthorizationServerProvider 类中保持对容器的依赖是糟糕的设计,如原始代码所示。

更好的方法是为 UserService 类使用一个工厂,而不是直接从容器中提取它。下一个代码显示了如何执行此操作的示例:

首先,清除 global.asax 文件中的 Application_Start() 方法,并将所有启动代码放入 Owin Startup() 方法中。 Startup()方法的代码:

public class Startup
{
public void Configuration(IAppBuilder app)
{
var container = SimpleInjectorConfig.Register();

GlobalConfiguration.Configure(WebApiConfig.Register);

Func<IUserService> userServiceFactory = () =>
container.GetInstance<IUserService>();

var OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new ApiAuthorizationServerProvider(userServiceFactory)
};

// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}

请注意我是如何通过将完全配置的 Simple Injector 容器返回给调用者以便直接使用它来更改 SimpleInjectorConfig.Register() 函数的签名的。

现在更改ApiAuthorizationServerProvider 类的构造函数,以便可以注入(inject)工厂方法:

public class ApiAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
private Func<IUserService> userServiceFactory;

public ApiAuthorizationServerProvider(Func<IUserService> userServiceFactory)
{
this.userServiceFactory = userServiceFactory;
}

// other code deleted for brevity...

private IUserService userService
{
get
{
return this.userServiceFactory.Invoke();
}
}

public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
// other code deleted for brevity...
// Just use the service like this
User user = this.userService.Query(e => e.Email.Equals(context.UserName) &&
e.Password.Equals(context.Password)).FirstOrDefault();

// other code deleted for brevity...
}
}

这样,每次调用 GrantResourceOwnerCredentials() 方法时,您都会获得一个新的 UserService,并且 UserService 类背后的完整依赖关系图将随之而来您在简单注入(inject)器配置中定义的生命周期,而您仅在应用程序的组合根中依赖于容器。

关于c# - 依赖注入(inject)(使用 SimpleInjector)和 OAuthAuthorizationServerProvider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25997592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com