【问题标题】:ASP.Net Identity 2 - Why doesn't my filter work?ASP.Net Identity 2 - 为什么我的过滤器不起作用?
【发布时间】:2017-02-10 05:33:07
【问题描述】:

我尝试创建一个简单的过滤器来查看用户是否处于称为“系统管理员”的角色中,基本上是必须执行[Authorize(Roles = "System Administrator")] 的简写。我认为这会相当简单,但我对 MVC 也很陌生,所以也许我忽略了一些东西。

这是我的代码:

using System.Web.Mvc;

namespace site_redesign_web.Filters
{
    public class SystemAdminFilter : ActionFilterAttribute
    {
        string SysAdminRole = "System Administrator";

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.User != null)
            {
                var userSysAdmin = filterContext.RequestContext.HttpContext.User.IsInRole(SysAdminRole) == true;
                filterContext.ActionParameters["IsSysAdmin"] = userSysAdmin;
            }
        }
    }
}

有人可以建议我哪里出错了吗?如果此人不是系统管理员,它会将他们定向到Home/NoPermissions,这将是一个巨大的优势。

谢谢!

【问题讨论】:

  • 你能公开你的过滤器的整个类吗?
  • 更新为显示整个班级。谢谢!
  • 这篇文章可能有助于更好地理解code.msdn.microsoft.com/ASPNET-MVC-5-Security-And-44cbdb97
  • 如果你从AuthorizeAttribute继承自定义过滤器会更容易?
  • 更新您要在其中实现此逻辑的控制器?

标签: c# asp.net asp.net-mvc asp.net-identity asp.net-mvc-filters


【解决方案1】:

更新:修复所有问题。 AJ。干得好... 终于解决了问题

using ActionFilterAttribute 
using System.Web.Mvc;
namespace site_redesign_web.Filters
{
    public class SystemAdminFilter : ActionFilterAttribute
    {
        string SysAdminRole = "System Administrator";
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.User != null)
            {
                var userSysAdmin = filterContext.RequestContext.HttpContext.User.IsInRole(SysAdminRole) == true;

            if(!userSysAdmin)
            {
                filterContext.Result = new RedirectToRouteResult(
                    new System.Web.Routing.RouteValueDictionary{
                    {"controller", "Home"},     
                    {"action", "Index"}
                });
            }
            }
        }
    }
}

你的控制器应该是

[SystemAdminFilter]     // at controller level
public SomeController : Controller
{

}

或者您也可以通过这样的注释将其用于特定的动作

public SomeController : Controller
{
    [SystemAdminFilter]     // at Action level
    public ActionResult SomeAction()
    {
            // perform your actions
    }

它会起作用,因为我在 Global.asax 的 Application_AuthorizeRequest 中手动传递了具有他角色的用户

protected void Application_AuthorizeRequest(Object sender, EventArgs e)
{
     FormsAuthenticationTicket formsAuthenticationTicket = new FormsAuthenticationTicket("Aravind", true, 30);
     FormsIdentity formsIdentityId = new FormsIdentity(formsAuthenticationTicket);
     GenericPrincipal genericPrincipal = new GenericPrincipal(formsIdentityId, new string[] { "SystemUser" }); //TEST with this redirected to Home Index place
     HttpContext.Current.User = genericPrincipal ;
}

我做的下一个测试是用这个

GenericPrincipal genericPrincipal = new GenericPrincipal(formsIdentityId, new string[] { "System Administrator" }); //TEST with this did not perform an action

【讨论】:

  • 当我尝试实现这个时,我得到: HTTP 错误 404.15 - 未找到 请求过滤模块被配置为拒绝查询字符串太长的请求。 URL 最终超过 2k 长。
  • 您是在 App_Start\FilterConfig 的 RegisterGlobalFilters 方法中添加过滤器吗?
  • 是的!真的不知道怎么回事,很奇怪!谢谢!
  • 您需要帮助吗?
  • 是的,我不知道我的下一步应该是什么。现在我想知道这是否真的值得麻烦......你有什么建议吗?
【解决方案2】:

由于您正在处理授权,我将扩展AuthorizeAttribute 而不是ActionFilterAttribute,这是一般模式。您只需要覆盖一种方法 - HandleUnauthorizedRequest,它在授权失败时执行。 AuthorizeAttribute 的默认实现已经为您处理了基于角色的授权。

public class SystemAdminAttribute : AuthorizeAttribute
{
    private const string SysAdminRole = "System Administrator";

    public SystemAdminFilter()
    {   
        //this defines the role that will be used to authorize the user:
        this.Roles = SysAdminRole;
    }  

    //if user is not authorized redirect to "Home/NoPermissions" page
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
        else
        {
            filterContext.Result = new RedirectToRouteResult(new
               RouteValueDictionary(new { controller = "Home", action = "NoPermissions" }));
         }
     }           
}

一旦你的属性被实现,用它装饰相应的控制器或动作:

[SystemAdmin]
public SysAdminController : Controller
{
}

【讨论】:

  • 看起来不错,但是当我实现它时,它会将匿名用户抛出到 NoPermissions 页面。它仅在我以系统管理员权限登录时有效。
  • 这很奇怪,因为当用户未通过身份验证时(此条件为真:!filterContext.HttpContext.User.Identity.IsAuthenticated),会执行以下行:base.HandleUnauthorizedRequest(filterContext); 应该重定向到登录页面。你的 web.config 中有类似的东西吗? ''
  • 是的,当我在没有系统管理员角色的情况下登录时,我得到:本地主机页面不工作本地主机重定向您太​​多次。
  • 这很可能是因为 NoPermissions 操作或 Home 控制器装饰有 SystemAdmin 属性 - 这会导致无限循环的重定向...
  • 我只有几个操作的 SystemAdmin 过滤器;这些都没有在 HomeController 上实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多