如何显示拒绝访问而不是重定向到登录页面?

Posted

技术标签:

【中文标题】如何显示拒绝访问而不是重定向到登录页面?【英文标题】:How to show Access Denied instead of redirecting to login page? 【发布时间】:2020-06-19 07:46:28 【问题描述】:

我在带有 OWIN 的 ASP.NET MVC 5 应用程序中使用 ASP.NET Identity 2。到目前为止,如果经过身份验证的用户尝试访问他没有角色的操作,他将被重定向到登录页面。在这种情况下,如何使经过身份验证的用户获得 AccessDenied 页面,但未经身份验证的用户仍会被发送到登录页面?

ConfigureAuth方法如下:

public void ConfigureAuth(IAppBuilder app)

    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
        
        
    );
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    app.UseSaml2Authentication(GetSamlOptions());


【问题讨论】:

更新 ("/Account/Login") 到您的拒绝访问视图。 @LinkedListT 这不适用于未经身份验证的用户! 您是否在控制器/动作之上指定任何角色? 是的,许多操作都有Authorize 具有特定角色。 我认为您最好的选择是创建一个继承自 AuthorizeAttribute 的类并覆盖 OnAuthorization() 。然后在该方法中,检查请求是否经过身份验证且未授权。 【参考方案1】:

试试这个自定义的授权属性,它不会重定向而是替换内容,所以 url 是完整的,并且还支持 ajax 请求:

    public class AppAuthorizeAttribute : AuthorizeAttribute
    

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        
            var isAuthorized = base.AuthorizeCore(httpContext);
            if (!isAuthorized)
            
                return false;
            
            // do another checks here...
        

        // This will be executed when AuthorizeCore returns false
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        
            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                
                    var urlHelper = new UrlHelper(filterContext.RequestContext);
                    filterContext.HttpContext.Response.StatusCode = 403;
                    filterContext.Result = new JsonResult
                    
                        Data = new
                        
                            ErrorMessage = "Unauthorized"
                        ,
                        JsonRequestBehavior = JsonRequestBehavior.AllowGet
                    ;
                
                else
                
                    filterContext.Result = new ViewResult
                    
                        ViewName = "~/Views/Error/AccessDenied.cshtml"
                    ;
                
            
            else
            
                base.HandleUnauthorizedRequest(filterContext);
            
        

    

将所有[Authorize] 替换为您的自定义属性[AppAuthorize]

【讨论】:

您过滤的是IsAjaxRequest,而不是IsAuthenticated 它首先检查IsAuthenticated是否为真,然后检查是否IsAjaxRequest【参考方案2】:

您可以根据角色使用自定义[DataAnnotations] 来授予特定用户访问权限。类似的东西:


[OnlyAllowedAttribute("Roles=Admin")]
public IActionResult OnlyAuthenticatedUsers()

  return View();


public class OnlyAllowedAttribute: AuthorizeAttribute

    public override void OnAuthorization(AuthorizationContext filterContext)
    
        base.OnAuthorization(filterContext);

        if(Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated)
        
          if(filterContext.Result is HttpUnauthorizedResult)
          
              filterContext.Result = new RedirectResult("~/Account/AcessDenied");
          
        
        else
        
          filterContext.Result = new RedirectResult("~/Account/Login");
        
    

https://***.com/a/1279854/9936356

【讨论】:

我认为您还必须检查是否未经身份验证。在您的代码中,这两种情况都会发生。 不是从线程获取Identity,我不应该从filterContext.HttpContext.user.Identity获取它吗?【参考方案3】:

我实现了一个自定义的授权属性如下:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class CustomAuthorizeAttribute : AuthorizeAttribute

    public override void OnAuthorization(AuthorizationContext filterContext)
    
        base.OnAuthorization(filterContext);
        if (filterContext.Result is HttpUnauthorizedResult)
        
            var route_values = new RouteValueDictionary
            
                ["controller"] = "Account"
            ;
            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            
                route_values["action"] = "AccessDenied";
            
            else
            
                route_values["action"] = "Login";
                route_values["returnUrl"] = filterContext.HttpContext.Request.Url.PathAndQuery;
            
            filterContext.Result = new RedirectToRouteResult(route_values);
        
    

我仍然愿意接受任何利用某些 OWIN 配置值的答案。

感谢所有提供帮助的人。

【讨论】:

以上是关于如何显示拒绝访问而不是重定向到登录页面?的主要内容,如果未能解决你的问题,请参考以下文章

登录成功后访问登录页面时出现Spring安全访问被拒绝消息。它应该重定向到默认页面

如何使授权属性返回自定义 403 错误页面而不是重定向到登录页面

在 Drupal 的 UberCart 结帐期间重定向到注册页面而不是登录页面?

TYPO3:404 用于受限访问页面而不是登录表单

登录 NEXT-AUTH 后重定向到自定义 URL

使用 API 路由时,在未授权时返回 Http Response 401 而不是重定向到登录页面