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

C# 属性要求用户登录而不是拒绝访问?,c#,asp.net-mvc-2,forms-authentication,roles,C#,Asp.net Mvc 2,Forms Authentication,Roles,更新:感谢这里的帮助,我创建了以下解决方案: public class CustomAuthorize : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs

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

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属性设置为roles of admin only(下面)。我的登录用户是作者。当我单击“删除”时,它会要求我登录,即使我已经登录了。我可以将返回拒绝访问视图的逻辑放在哪里

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");
        }
    }
    [Authorize(Roles="Admin")]
    public ActionResult Delete(int id)
SpotlightController.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");
        }
    }
    [Authorize(Roles="Admin")]
    public ActionResult Delete(int id)

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

谢谢


Hal

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

以下是AuthorizationAttribute的功能,即开箱即用:它检查当前用户是否被授权处理当前请求,并返回HHTP 401/UNAUTHORIZED,如果它们未登录,或者它们不在当前请求的授权用户/角色列表中,则返回HHTP 401/UNAUTHORIZED

如果在web.config中配置了loginUrl属性,则为。一般的想法是,如果一个用户因为没有登录而被拒绝访问该站点,那么他们接下来要做的就是登录


因为您想做的是重定向到其他地方,所以哈尔提出的覆盖HandleUnauthorizedRequest和重定向的建议并不是不合理的。请记住,如果您仍然希望未经验证的用户查看登录页面(与已验证的用户相反,但不在允许的用户/角色列表中),那么您必须为此添加逻辑。我建议不要凌驾于核心授权或授权之上;这两种方法都不能解决问题,而且它们比HandleUnauthorizedRequest更容易出错。

我想我不明白为什么HandleUnauthorizedRequest现在什么都不做了?或者我只是没有捕获那个事件?你的登录用户是作者,不是管理员?期望的行为是,权限不足的用户将被重定向到异常页面,而不是尝试使用提升的凭据登录的页面(我认为这是默认行为)。我理解正确吗?我认为HandleUnauthorizedRequest是在做应该做的事情——给你一个提升特权的机会。您必须在自定义属性(或其他扩展点)中重写该行为。希望有帮助。如果你真的需要写属性的帮助,请告诉我。Craig是绝对正确的-你必须处理a角色例外与未经身份验证的用户。我不认为这太难,但我还没试过这么多。我也建议不要弄乱授权代码或授权,除非你真的想实现你自己的身份验证方案。我需要阅读更多。与此同时,我需要一些帮助来覆盖HandleUnauthorizedRequest。我知道如何滚动从AuthorizeAttribute继承的自己的类,然后重写HandleUnauthorizedRequest。我不需要我自己的属性,因为这是我唯一改变的东西。那么,如何在不派生的情况下重写HandleUnauthorizedRequest呢?您必须派生一个新类型并重写该方法。但这种方法是你唯一需要改变的。