Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC在控制器实例化之前进行身份验证_C#_Asp.net Mvc_Authentication_Openid_Owin - Fatal编程技术网

C# ASP.NET MVC在控制器实例化之前进行身份验证

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,用户信息在他们登录之前不存在(在安装控制器之后发生) 我(在其他帖子中)听说有一种

我有一个控制器,将服务接口注入构造函数。 服务的构造函数中也注入了接口。 IoC容器(Unity)在构造它为给定接口返回的一个类时,需要使用有关用户的信息

发生的情况是,在计算[Authorize]属性并对用户进行身份验证之前,正在实例化控制器。这迫使Unity在用户登录之前执行依赖项注入并使用有关用户的信息。当我们使用集成windows身份验证时,这些都不是问题,但现在我们使用OpenID连接到Azure AD,用户信息在他们登录之前不存在(在安装控制器之后发生)

我(在其他帖子中)听说有一种方法可以将我的owin启动类配置为在过程的早期移动身份验证,但我找不到任何关于如何执行此操作的示例。我需要在实例化控制器之前进行身份验证

这里是一个简单的例子,我有

控制器:

[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;
    }
}