我目前正在更新使用 MembershipProvider 和 RoleProvider 的旧 ASP.NET Webforms 应用程序,以使用较新的 ASP.NET Identity 类。此外,我使用 Autofac 进行依赖项注入(inject),为了保持一致性,我希望能够将它与新的身份类一起使用。
ASP.NET Identity 现在依赖于 OWIN 中间件,我已经通过添加以下 Startup.cs 类成功地将 OWIN 中间件设置合并到我的应用程序中:
internal partial class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
AutofacConfig.RegisterTypes(builder);
AutofacConfig.RegisterIdentityTypes(builder, app);
var container = builder.Build();
Global.SetContainer(container);
app.UseAutofacMiddleware(container);
ConfigureAuth(app);
}
}
我像这样用 Autofac 注册身份类:
internal static class AutofacConfig
{
public static void RegisterIdentityTypes(ContainerBuilder builder, IAppBuilder app)
{
builder.RegisterType<ApplicationUserStore>().As<IUserStore<ApplicationUser>>().InstancePerRequest();
builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
builder.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerRequest();
builder.Register(c => app.GetDataProtectionProvider()).InstancePerRequest();
}
}
当我导航到我的 WebForms 登录页面时,我可以看到下面的 ApplicationSignInManager 类被实例化并且它的构造函数参数也被解析,这表明 Autofac 正在正常工作。
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public ApplicationSignInManager(
ApplicationUserManager userManager,
IAuthenticationManager authenticationManager)
: base(userManager, authenticationManager)
{
// userManager is valid
// authenticationManager is valid
}
}
当我在我的 WebForms 登录页面上单击我的登录按钮时,将调用以下方法并通过 Autofac 属性注入(inject)实例化 ApplicationSignInManager。然后调用正确的 Identity 类实现。
public partial class SignIn : BasePage
{
// Autofac property injection
public ApplicationSignInManager ApplicationSignInManager { get; set; }
....
protected void SignInClick(object sender, EventArgs e)
{
// Validate the user password
var result = this.ApplicationSignInManager.PasswordSignIn(
this.email.Text,
this.password.Text,
this.remember.Checked,
true);
....
}
所以一切似乎都很好,但对我来说似乎有些不对,我看不到 OWIN 和 Autofac 连接在哪里,甚至不需要。如果我从 Startup.cs 中删除以下行,则会火上浇油...
app.UseAutofacMiddleware(container);
...一切正常!哪个不对,不是吗?
许多 MVC 示例似乎表明这是获取 Identity 对象的正确方法(通过 GetOwinContext() 调用):
protected void SignInClick(object sender, EventArgs e)
{
var signInManager = this.Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();
// Validate the user password
var result = signInManager.PasswordSignIn(
this.email.Text,
this.password.Text,
this.remember.Checked,
true);
....
}
但是在执行该代码时,“signInManager”变量始终为 NULL。
我真的需要这行代码吗?
app.UseAutofacMiddleware(container);
谁能指出我正确的方向?
请您参考如下方法:
For a simple scenario, app.UseAutofacMiddleware(container); will handle both adding an Autofac lifetime to the OWIN request scope as well as adding middleware that is registered with Autofac into the pipeline.
参见 source确认。
基本上,如果您要将 Autofac 中的任何内容注入(inject) OWIN 管道(即中间件),则需要这一行。但是对于您的场景,您似乎没有做任何类似的事情,因此删除该行不会为您带来任何改变。
至于从 OWIN 管道解析对象,您实际上不需要这样做 - 您已经从 Autofac 解析了对象。但是,SecurityStampValidator 仍然从 OWIN 解析 ApplicationUserManager,因此您仍然需要向 OWIN 注册它:
app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());
参见 this question/answer其背后的原因。
