C# 当用户在 asp.net mvc3 中未被授权时重定向到另一个页面

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10928277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 15:47:14  来源:igfitidea点击:

Redirect to another page when user is not authorized in asp.net mvc3

c#asp.netasp.net-mvcasp.net-mvc-3

提问by Snake Eyes

I've read

我读了

How to easily redirect if not authenticated in MVC 3?and Redirect to AccessDenied page when user is not authorizedbut the link from an answer (means http://wekeroad.com/2008/03/12/aspnet-mvc-securing-your-controller-actions/) doesn't work.

如果未在 MVC 3 中进行身份验证,如何轻松重定向?当用户未经授权但来自答案的链接(意味着http://wekeroad.com/2008/03/12/aspnet-mvc-securing-your-controller-actions/)不起作用重定向到 AccessDenied 页面

I put

我放

[Authorize(Users = "test")]
    public class RestrictedPageController: Controller
    {

        public ActionResult Index()
        {
           return View();
        }

 ....
    }

And in my web.config, I have already

在我的 web.config 中,我已经

 <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
 </authentication>

accordingly with https://stackoverflow.com/a/6770583/998696

相应地与https://stackoverflow.com/a/6770583/998696

But when I want to access /RestrictedPage/Index, it must redirect me to other page (from other controller). Instead of this, the error appears like:

但是当我想访问时/RestrictedPage/Index,它必须将我重定向到其他页面(来自其他控制器)。取而代之的是,错误显示如下:

Server Error in '/Project' Application.

The view 'LogOn' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Account/LogOn.aspx
~/Views/Account/LogOn.ascx
~/Views/Shared/LogOn.aspx
~/Views/Shared/LogOn.ascx
~/Views/Account/LogOn.cshtml
~/Views/Account/LogOn.vbhtml
~/Views/Shared/LogOn.cshtml
~/Views/Shared/LogOn.vbhtml

Before login, the Logonpage form appears correctly but the above error appears when accessing /RestrictedPage/Indexpage. I can login with user different one authorized to access RestrictedPagepage.

登录前,Logon页面表单正确显示,但访问/RestrictedPage/Index页面时出现上述错误。我可以使用不同的用户登录访问RestrictedPage页面。

Where is my mistake and how setup redirection ?

我的错误在哪里以及如何设置重定向?

采纳答案by VJAI

The default Authorizeattribute behaves in such a way that when the user is not authenticatedor authenticated but not authorizedthen it set the status code as 401 (UnAuthorized). When the filter sets the status code as 401the ASP.NET framework checks if the website has forms authentication enabled and if it is then redirects to loginUrlparameter set up there.

默认Authorize属性的行为方式是,当用户未经过身份验证或经过身份验证但未授权时,它将状态代码设置为401 (UnAuthorized)。当过滤器将状态代码设置为401 时,ASP.NET 框架会检查网站是否启用了表单身份验证,然后重定向到loginUrl那里设置的参数。

If you want to change that behavior say you want to redirect the user to an AccessDeniedcontroller if the user is authenticated but not authorized then you have to extend the Authorizeattribute and override the HandleUnauthorizedRequestmethod.

如果您想更改该行为,例如,AccessDenied如果用户已通过身份验证但未经授权,您想将用户重定向到控制器,那么您必须扩展该Authorize属性并覆盖该HandleUnauthorizedRequest方法。

For ex.

例如。

public class CustomAuthorize: AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
        else
        {
           filterContext.Result = new RedirectToRouteResult(new 
               RouteValueDictionary(new { controller = "AccessDenied" }));
        }
    }
}

You can override the HandleUnauthorizedRequestas per your need and then you have to mark the controller actions to use the CustomAuthorizeattribute instead of the built-in one.

您可以HandleUnauthorizedRequest根据需要覆盖,然后您必须标记控制器操作以使用该CustomAuthorize属性而不是内置属性。

回答by manny

Yes, it is correct as you mentioned in web.config

是的,正如您在 web.config 中提到的那样正确

<forms loginUrl="~/Account/LogOn" timeout="2880" />

redirection is looking for Account controller and LogOn actionresult. If you want to redirect your page, change there instead of account and logon

重定向正在寻找帐户控制器和登录操作结果。如果您想重定向您的页面,请更改那里而不是帐户和登录

回答by karaxuna

Place "/Account/LogOn" Instead of "~/Account/LogOn"

放置“/Account/LogOn”而不是“~/Account/LogOn”

回答by Yuthasak

I like Mark's Answer,
but I don't want to change all of my action attributes
from [Authorize] to [CustomAuthorize]

我喜欢 Mark 的回答,
但我不想将我的所有操作属性
从 [Authorize] 更改为 [CustomAuthorize]

I edit Login()action on AccountController
and check Request.IsAuthenticatedbefore show view
I think, if the authenticated user go to /Account/Logon,
I will redirect to /Error/AccessDenied.

我在显示视图之前编辑Login()操作AccountController
并检查 我认为,如果经过身份验证的用户转到, 我将重定向到.Request.IsAuthenticated
/Account/Logon
/Error/AccessDenied

    [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        if (Request.IsAuthenticated)
        {
            return RedirectToAction("AccessDenied", "Error");
        }

        ViewBag.ReturnUrl = returnUrl;

        return View();
    }

回答by Riddik

Since I did not want to override AuthorizeAttributeI used filter

由于我不想覆盖AuthorizeAttribute我使用过滤器

public class RedirectFilter : ActionFilterAttribute
{
   public override void OnActionExecuting(ActionExecutingContext filterContext)
    {

        if (!IsAuthorized(filterContext))
        {
            filterContext.Result =
                new RedirectToRouteResult(new RouteValueDictionary(new {controller = "AccessDenied"}));
        }
    }

    private bool IsAuthorized(ActionExecutingContext filterContext)
    {
        var descriptor = filterContext.ActionDescriptor;
        var authorizeAttr = descriptor.GetCustomAttributes(typeof(AuthorizeAttribute), false).FirstOrDefault() as AuthorizeAttribute;

        if (authorizeAttr != null)
        {
            if(!authorizeAttr.Users.Contains(filterContext.HttpContext.User.ToString()))
            return false;
        }
        return true;

    }
}