C# ASP.NET MVC在控制器实例化之前进行身份验证
我有一个控制器,将服务接口注入构造函数。 服务的构造函数中也注入了接口。 IoC容器(Unity)在构造它为给定接口返回的一个类时,需要使用有关用户的信息 发生的情况是,在计算[Authorize]属性并对用户进行身份验证之前,正在实例化控制器。这迫使Unity在用户登录之前执行依赖项注入并使用有关用户的信息。当我们使用集成windows身份验证时,这些都不是问题,但现在我们使用OpenID连接到Azure AD,用户信息在他们登录之前不存在(在安装控制器之后发生) 我(在其他帖子中)听说有一种方法可以将我的owin启动类配置为在过程的早期移动身份验证,但我找不到任何关于如何执行此操作的示例。我需要在实例化控制器之前进行身份验证 这里是一个简单的例子,我有 控制器:C# ASP.NET MVC在控制器实例化之前进行身份验证,c#,asp.net-mvc,authentication,openid,owin,C#,Asp.net Mvc,Authentication,Openid,Owin,我有一个控制器,将服务接口注入构造函数。 服务的构造函数中也注入了接口。 IoC容器(Unity)在构造它为给定接口返回的一个类时,需要使用有关用户的信息 发生的情况是,在计算[Authorize]属性并对用户进行身份验证之前,正在实例化控制器。这迫使Unity在用户登录之前执行依赖项注入并使用有关用户的信息。当我们使用集成windows身份验证时,这些都不是问题,但现在我们使用OpenID连接到Azure AD,用户信息在他们登录之前不存在(在安装控制器之后发生) 我(在其他帖子中)听说有一种
[Authorize]
public class MyController : Controller
{
private readonly IMyService myService;
public MyController(IMyService myService)
{
this.myService = myService;
}
// ...
}
统一配置:
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
// ...
return container
.RegisterType<ISomeClass, SomeClass>()
.RegisterType<IMyService>(new InjectionFactory(c =>
{
// gather info about the user here
// e.g.
var currentUser = c.Resolve<IPrincipal>();
var staff = c.Resolve<IStaffRepository>().GetBySamAccountName(currentUser.Identity.Name);
return new MyService(staff);
}));
}
}
在网上找不到任何专门针对我的问题的东西后,我决定深入研究这个问题。我发现我可以创建一个自定义IControllerFactory(或从DefaultControllerFactory继承),在这里我可以定义CreateController方法 在CreateController期间,我检查用户是否经过身份验证。如果是的话,我只是让DefaultControllerFactory像平常一样创建控制器 如果用户没有经过身份验证,我将创建我的(非常)简单的“Auth”控制器,而不是请求的控制器(具有多个依赖层的控制器),RequestContext保持不变 Auth控制器将被实例化,没有问题,因为它没有依赖项。注意:从未在Auth控制器上执行任何操作。一旦创建了Auth控制器,全局authorized属性就会生效,并指示用户进行身份验证(通过OpenID连接到Azure AD和ADFS) 登录后,他们将被重定向回我的应用程序,而原始RequestContext仍处于tact状态。CusomControllerFactory将用户视为经过身份验证,并创建请求的控制器 这种方法对我来说非常有用,因为我的控制器有一个很大的依赖链被注入(即控制器依赖于ISomeService,它依赖于许多异构位置、ISomeHelper、ISomethingEles…),并且在用户登录之前,所有依赖项都不会被解析 对于如何实现我在最初的问题中提出的要求,我仍然愿意听取其他(更优雅的)想法
CustomControllerFactory.cs
public class CustomControllerFactory : DefaultControllerFactory
{
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var user = HttpContext.Current.User;
if (user.Identity.IsAuthenticated)
{
return base.CreateController(requestContext, controllerName);
}
var routeValues = requestContext.RouteData.Values;
routeValues["action"] = "PreAuth";
return base.CreateController(requestContext, "Auth");
}
}
Global.asax.cs
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
// ...
ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
}
// ...
}
AuthController.cs
public class AuthController : Controller
{
public ActionResult PreAuth()
{
return null;
}
}
我也被这个绊倒了,虽然没有任何DI的东西。在基本控制器的构造函数中需要一个用户ID,并且惊讶地看到在
AuthorizedAttribute
移动用户之前调用了构造函数。解释了为什么会这样
public class AuthController : Controller
{
public ActionResult PreAuth()
{
return null;
}
}