我正在使用Autofac进行Inversion of Control容器,其配置如下
public void Configuration(IAppBuilder app) {
configureIoC(app);
configureAuth(app);
}
void configureIoC(IAppBuilder app) {
var b = new ContainerBuilder();
//...
b.Register(c => HttpContext.Current?.User?.Identity
?? new NullIdentity()).InstancePerLifetimeScope();
var container = b.Build();
app.UseAutofacMiddleware(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
我认为这是Autofac与其他容器的事实可能与我所看到的无关。这里的关键行是配置IIdentity
的任何依赖关系,以便从HttpContext.Current
中提取。
我这样使用它,以便我可以随时随地访问当前用户。
public interface ICurrentUser {
Task<AppUser> Get();
}
public class CurrentUserProvider : ICurrentUser {
public async Task<AppUser> Get() => await users.FindByNameAsync(currentLogin.GetUserId());
public CurrentUserProvider(AppUserManager users, IIdentity currentLogin) {
this.users = users;
this.currentLogin = currentLogin;
}
}
我在过去的项目中使用了这种模式并且运行正常。我目前正在将它应用于现有项目并看到一件非常奇怪的事情。
ICurrentUser
时,一切正常ICurrentUser
的实例时,Get
操作失败,因为IIdentity
的实例尚未从cookie中解析而不是但已将声明加载到其中(AuthenticationType == null
)!奇怪的是,如果我在实例化WebApi控制器后暂停调试器,我可以点击HttpContext.Current.User.Identity
并看到AuthenticationType == "Cookie"
并且所有声明都在那里。这导致我得出的结论是,某些事情按照以下顺序发生
HttpContext
身份这当然毫无意义!
所以问题如下
请不要建议我创建一个IdentityProvider
来解决IIdentity
。我理解如何解决这个问题,我不明白为什么会发生这种情况以及如何控制事物的管道顺序。
答案 0 :(得分:1)
我修改了你的代码,因为我没有NullIdentity()
且你的CurrentUserProvider
没有在这里编译。
我安装了这些软件包:
我的Startup.cs看起来像这样:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
configureIoC(app);
ConfigureAuth(app);
}
void configureIoC(IAppBuilder app) {
var b = new ContainerBuilder();
//...
b.RegisterType<CurrentUserProvider>().As <ICurrentUser>().InstancePerLifetimeScope();
b.Register(c => HttpContext.Current.User.Identity).InstancePerLifetimeScope();
b.RegisterControllers(typeof(MvcApplication).Assembly);
b.RegisterApiControllers(typeof(MvcApplication).Assembly);
var x = new ApplicationDbContext();
b.Register<ApplicationDbContext>(c => x).InstancePerLifetimeScope();
b.Register<UserStore<ApplicationUser>>(c => new UserStore<ApplicationUser>(x)).AsImplementedInterfaces().InstancePerLifetimeScope();
b.RegisterType<ApplicationUserManager>().InstancePerLifetimeScope();
b.RegisterType<ApplicationSignInManager>().InstancePerLifetimeScope();
var container = b.Build();
app.UseAutofacMiddleware(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
您的ICurrentUser
内容:
public interface ICurrentUser
{
Task <ApplicationUser> Get();
}
public class CurrentUserProvider : ICurrentUser
{
private ApplicationUserManager users;
private IIdentity currentLogin;
public async Task<ApplicationUser> Get()
{
return await users.FindByNameAsync(currentLogin.GetUserId());
}
public CurrentUserProvider(ApplicationUserManager users, IIdentity currentLogin)
{
this.users = users;
this.currentLogin = currentLogin;
}
}
因此Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
我的HomeController
非常简单:
public class HomeController : Controller
{
private ICurrentUser current;
public HomeController(ICurrentUser current)
{
this.current = current;
}
public ActionResult Index()
{
var user = current.Get();
if (user == null)
throw new Exception("user is null");
return View();
}
}
...最后是一个简单的ApiController,我通过输入 localhost / api / TestApi / 5 来访问:
public class TestApiController : ApiController
{
private ICurrentUser current;
public TestApiController(ICurrentUser current)
{
this.current = current;
}
public string Get(int id)
{
var user = current.Get();
if (user == null)
throw new Exception("user is null");
return "";
}
}
如果我刚启动项目(甚至没有登录),我会收到一个GenericIdentity对象来支持IIdentity接口,看看这个:
当我在Get()
方法中介入(F11)时,IIdentity
已正确设置为GenericIdentity
,因为实际上没有人登录应用程序。这就是为什么我认为你实际上并不需要那个NullableIdentity。
尝试将您的代码与我的代码进行比较并修复您的代码,以便我们查看它是否有效,然后最终您会发现问题的真正原因,而不仅仅是修复它(我们开发人员喜欢知道为什么有些东西正常工作。