【问题标题】:Hybrid of Windows Authentication and Forms Authentication in ASP.NET MVC 4ASP.NET MVC 4 中 Windows 身份验证和表单身份验证的混合
【发布时间】:2013-07-03 18:21:03
【问题描述】:

我们有一个 ASP.NET MVC 4 Intranet 应用程序。我们正在使用 Windows 身份验证,这方面工作正常。使用了用户的凭据,我们可以从 Web 应用程序访问这些凭据。

然而,我们真正想要的是某种混合模式。我们想从浏览器中获取用户的凭据,但我们也想验证用户是否在我们应用程序的数据库中。如果用户在数据库中,那么他们可以继续。如果不是,我们希望将它们重定向到要求备用凭据的页面。我现在要做的是,在Global.asax.cs 中,我有一个Application_AuthenticateRequest 方法,我正在检查用户是否经过身份验证。如果他们是并且他们的 cookie 信息不能反映他们已登录系统的事实,那么我将他们登录并设置一些包含用户信息的 cookie。如果他们没有通过身份验证,我会将他们重定向到登录页面。由于公司政策涉及的原因,我们不能使用 AD 角色,因此我们需要使用数据库进行额外的身份验证。

我猜Application_AuthenticateRequest 不是这样做的地方,但也许是。但是我们基本上需要一个地方来过滤身份验证请求。但此外,这个实现还引出了另一个问题:

我们的应用中有某些 URL 允许匿名访问。我已经为这些添加了<location> 标签到 web.config。问题是,当对这些进行匿名调用时,它会到达Application_AuthenticateRequest 并尝试将用户登录到数据库中。现在,我可以在Application_AuthenticateRequest 中添加代码来处理这些 URL,这是我目前的计划,但是如果我正在写,而Application_AuthenticateRequest 不是这样做的地方,那么我宁愿现在弄清楚而不是稍后。

【问题讨论】:

    标签: asp.net-mvc iis windows-authentication form-authentication


    【解决方案1】:

    您需要为此目的使用操作过滤器。您可以像这样扩展 AuthorizeAttribute:

    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        private UnitOfWork _unitOfWork = new UnitOfWork();
    
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var isAuthorized = false;
            var username = httpContext.User.Identity.Name;
            // Some code to find the user in the database...
            var user = _unitOfWork.UserRepository.Find(username);
            if(user != null)
            {
               isAuthorized = true;
            }
    
    
            return isAuthorized;
        }
    
        public override void OnAuthorization(AuthorizationContext filterContext)
        {            
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
    
            if (AuthorizeCore(filterContext.HttpContext))
            {
                SetCachePolicy(filterContext);
            }
            else
            {
               // If not authorized, redirect to the Login action 
               // of the Account controller... 
              filterContext.Result = new RedirectToRouteResult(
                new System.Web.Routing.RouteValueDictionary {
                   {"controller", "Account"}, {"action", "Login"}
                }
              );               
            }
        }
    
        protected void SetCachePolicy(AuthorizationContext filterContext)
        {
            // ** IMPORTANT **
            // Since we're performing authorization at the action level, 
            // the authorization code runs after the output caching module. 
            // In the worst case this could allow an authorized user 
            // to cause the page to be cached, then an unauthorized user would later 
            // be served the cached page. We work around this by telling proxies not to 
            // cache the sensitive page, then we hook our custom authorization code into 
            // the caching mechanism so that we have the final say on whether a page 
            // should be served from the cache.
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidationHandler, null /* data */);
        }
    
        public void CacheValidationHandler(HttpContext context,
                                            object data,
                                            ref HttpValidationStatus validationStatus)
        {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }
    }
    

    然后,您可以像这样在 Controller 级别或 Action 级别使用此属性:

    [MyAuthorize]
    public ActionResult SomeAction()
    {
      // Code that is supposed to be accessed by authorized users only
    }
    

    【讨论】:

    • 我喜欢这个解决方案,但我仍然在控制器方法上遇到 401 错误,应该允许任何人。在这种特殊情况下,我从 C# HttpWebRequest.GetResponse() 调用中调用它。 DebugController.FlushCaches() 有 [AllowAnonymous] 并且在web.config 我有一个<location> 标记Debug/FlushCaches<allow users="*"/>。但是当我的HttpWebRequest 调用它时,我得到了 401。
    • 使用它作为你的 标签:<location path="Debug/FlushCaches"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location>
    • 这就是我在配置文件中的内容,因为我试图在你上面的评论中解释。
    • 我发现了问题。我们在 IIS 中禁用了匿名身份验证。我重新启用了它,一切似乎又恢复了。谢谢。
    猜你喜欢
    • 2020-06-21
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2011-03-12
    • 2012-10-23
    • 1970-01-01
    相关资源
    最近更新 更多