在global.asax中设置的用户仅在下一个请求后可用

时间:2014-08-25 11:47:07

标签: asp.net .net asp.net-mvc global-asax claims-based-identity

我正在使用带有Windows身份验证的ASP.NET MVC 4构建Intranet应用程序。在global.asax文件中,我实现了这个方法:

protected void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs args)

在此方法中,我创建了一个新的ClaimsIdentity并为其设置args.User,就像example on MSDN一样。稍后在应用程序中,在其中一个控制器中,我需要从数据库中获取一些数据。由于我已经有一个执行此操作的API操作,因此我从Controller中调用该API(同步)。

API使用ApiController.User属性获取当前用户的声明。但是,这些声明不是我在global.asax中设置的声明。实际上,它们是在此请求之前对用户的声明。

奇怪的是(对我而言)是下次我打电话给应用程序时,新的声明到位了。因此,在我的情况下,我更改后来决定哪些按钮对用户可见的声明,但只有在用户向应用程序发出另一个请求后,才会更新这些按钮。

如何确保我在global.asax中设置的声明立即生效?

额外信息:

我没有为每个请求设置声明。当这个方法执行时,我检查一些事情,看看用户是否仍然有效:cookie,用户不是匿名的,用户仍然是有效的"。后者由缓存决定 - 我保留一份仍然有效的用户列表,如果有人通过用户界面更新了他们的权限,他们将失效并在下一次请求中收到新的声明。

我已经附加了一个调试器,我看到我的代码被执行了,校长获得了我希望它仍然在这个方法中的所有声明。当我到达控制器操作时,ApiController.User会在此请求之前提出请求。当我发出另一个请求时,将跳过身份验证方法(因为用户名现在位于缓存中),并且在控制器中ApiController.User具有正确的声明。

3 个答案:

答案 0 :(得分:1)

您需要设置两个成员才能使其正常工作。

Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;

答案 1 :(得分:1)

我认为您不能在设置它们的同一请求中访问您的声明。设置索赔后尝试重定向。

答案 2 :(得分:0)

我做了类似的事情。这是我的代码,我希望它会有所帮助。

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
        {
            var clamisIdentityBuilder = DependencyResolver.Current.GetService<IClaimsIdentityBuilder>();
            var transformer = new ClaimsTransformer(clamisIdentityBuilder);
            var principal = transformer.Authenticate(string.Empty, ClaimsPrincipal.Current);

            // user if authenticated but Claims could not be created (they are not available in cache nor DB)
            if (principal == null)
            {
                var cacheProvider = DependencyResolver.Current.GetService<ICacheProvider>();
                cacheProvider.Clear();
                FormsAuthentication.SignOut();
                Response.Clear();
                string redirectUrl = FormsAuthentication.LoginUrl;
                Response.Redirect(redirectUrl);
            }
            else
            {
                Thread.CurrentPrincipal = principal;
                HttpContext.Current.User = principal;
            }
        }