属性要求用户登录而不是拒绝访问?

更新:感谢此处的帮助,我创建了以下解决方案:

public class CustomAuthorize : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs // If user is not logged in prompt if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { base.HandleUnauthorizedRequest(filterContext); } // Otherwise deny access else { filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary { {"controller", "Account"}, {"action", "NotAuthorized"} }); } } } 

我从NerdDinner开始,并使用FormsAuthentication和ActiveDirectory作为我的会员提供者。 我通过我的数据库使用Global.asax和AccountController(下面)添加了对角色的支持。

所以现在在我的控制器中,我的Authorize属性设置为仅限admin的角色(下面)。 我登录的用户是作者。 当我点击删除时,它会要求我登录,即使我已经这样做了。 我在哪里可以放置逻辑来返回拒绝访问视图?

的Global.asax.cs

  protected void Application_AuthenticateRequest(Object sender, EventArgs e) { HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie == null || authCookie.Value == "") { return; } FormsAuthenticationTicket authTicket = null; try { authTicket = FormsAuthentication.Decrypt(authCookie.Value); } catch { return; } if (Context.User != null) { string[] roles = authTicket.UserData.Split(new char[] { ';' }); Context.User = new GenericPrincipal(Context.User.Identity, roles); } } 

AccountController.cs

  [HttpPost] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "Needs to take same parameter type as Controller.Redirect()")] public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl) { if (!ValidateLogOn(userName, password)) { ViewData["rememberMe"] = rememberMe; return View(); } // Make sure we have the username with the right capitalization // since we do case sensitive checks for OpenID Claimed Identifiers later. userName = this.MembershipService.GetCanonicalUsername(userName); // Lookup user's (CWID) appropriate access level string accessLevel = userRepository.FindUserByUserName(userName).AccessLevel.LevelName; FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, //version userName, // user name DateTime.Now, //creation DateTime.Now.AddMinutes(30), //Expiration rememberMe, //Persistent accessLevel); // hacked to use roles instead string encTicket = FormsAuthentication.Encrypt(authTicket); this.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)); if (!String.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } 

SpotlightController.cs

  [Authorize(Roles="Admin")] public ActionResult Delete(int id) 

这是AuthorizeAttribute的function,开箱即用:它检查当前用户是否有权获得当前请求,如果不是,则返回HHTP 401 / UNAUTHORIZED,因为它们根本没有登录,或者它们不在当前请求的授权用户/角色列表中。

如果在web.config中配置了loginUrl属性,则Web窗体身份validationHTTP模块会看到此401响应,截获该响应并将其转换为对登录页面的HTTP 302(重定向)响应 。 一般的想法是,如果用户因为没有登录而被拒绝访问该站点,但他们想要做的下一件事就是登录。

由于您要做的是重定向到其他地方,Hal的建议覆盖HandleUnauthorizedRequest和重定向并非不合理。 请记住,如果您仍然希望未经过身份validation的用户能够看到登录页面(而不是经过身份validation的用户/角色列表),那么您必须为此添加逻辑。 我建议反对覆盖AuthorizeCore或OnAuthorization的想法; 这些都没有实际解决问题,并且它们比HandleUnauthorizedRequest更容易搞砸。

我想你可以从AuthorizeAttribute派生,然后重写HandleUnauthorizedRequest并在那里放置你自己的重定向逻辑。

谢谢,

哈尔

或者,您可以覆盖Authorize属性。 您将覆盖OnAuthorization方法并从您的基础获取AuthorizeCore方法的结果。 根据该结果,您可以在OnAuthirziation中抛出exception或自定义exception(即可能是记录状态的自定义安全exception)。