ERR_TOO_MANY_REDIRECTS中OnAuthentication,OnAuthenticationChallenge和OnAuthorization的组合结果

时间:2019-02-18 08:43:58

标签: c# asp.net-mvc-5

如果用户属于特定角色,我希望有条件访问特定控制器。该用户无法访问其他任何内容。如果用户不是该特定角色的用户,则将其转到常规站点。

我为此有两个ActionFilter:

CarParkAuthenticationAttribute

public class CarParkAuthenticationAttribute : FilterAttribute, IAuthenticationFilter
{

    public void OnAuthentication(AuthenticationContext filterContext)
    {
        var currentUser = ParseUserNameFromOkta(filterContext.HttpContext.User.Identity.Name);

        if (filterContext.HttpContext.Session[Constants.SessionVariableCurrentUser] == null)
        {
            var usersManager = new UsersManager();
            var userCarParkTask = Task.Run(() => usersManager.FindIntranetUser(currentUser));
            var userCarPark = userCarParkTask.WaitAndUnwrapException();

            if (userCarPark != null)
            {                    
                var roleTask = Task.Run(() => usersManager.GetRoleByUserId(userCarPark.IntranetUserId));
                var roles = roleTask.WaitAndUnwrapException();

                var carParkUser = new CarParkUser(userCarPark.EmployeeName, userCarPark, roles);

                filterContext.HttpContext.User = carParkUser;
                filterContext.HttpContext.Session[Constants.SessionVariableCurrentUser] = carParkUser;
                filterContext.HttpContext.Session[Constants.SessionVariableCurrentUserId] = carParkUser.Detail.IntranetUserId;
            }
            else
            {
                SystemLogger.Info("InternetCarParkUser was NOT found against: " + currentUser);
                filterContext.HttpContext.Response.Redirect("~/Views/Error/AccessDenied");
                filterContext.HttpContext.Response.End();
            }
        }
        else // Already signed in
        {
            if (filterContext.HttpContext.Session[Constants.SessionVariableCurrentUser] is CarParkUser user)
            {
                filterContext.HttpContext.User = user;
                filterContext.HttpContext.Session[Constants.SessionVariableCurrentUserId] = ((CarParkUser)filterContext.HttpContext.User).Detail.IntranetUserId;
            }
            else
            {
                filterContext.HttpContext.Response.Redirect("~/Views/Error/AccessDenied");
                filterContext.HttpContext.Response.End();
            }
        }
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        #region Valid User Check

        var user = filterContext.HttpContext.User;

        if ((CarParkUser)user == null || !user.Identity.IsAuthenticated)
        {
            filterContext.Result = new HttpUnauthorizedResult();
            return;
        }

        #endregion

        #region Confirm current user is on the list

        var isTargetRole = user.IsInRole("Mawgif");

        #endregion

        if (isTargetRole)
        {
            #region Confirming target controller/action

            var helper = new UrlHelper(filterContext.RequestContext);
            var url = helper.Action("CarParkRequest", "Mawgif");

            filterContext.Result = new RedirectResult(url);
        }
    }

}

CarParkAuthorizationAttribute

public class CarParkAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
    private static readonly ILog SystemLogger = LogManager.GetLogger("OnAuthorization");

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            SystemLogger.Error($"{nameof(filterContext)} was not found");
            throw new ArgumentNullException(nameof(filterContext));
        }

        if (!(filterContext.HttpContext.User is CarParkUser currentUser))
        {
            SystemLogger.Error($"{nameof(currentUser)} was not found or is not {nameof(CarParkUser)}");
            throw new ArgumentNullException(nameof(currentUser));
        }

        var controllerName = GetControllerName();
        var actionName = GetActionName();
        var isUserAllowed = currentUser.Roles != null && currentUser.Roles.Any(businessUserRole =>
                                businessUserRole.AllowedLocations.Any(w =>
                                    w.ControllerName == controllerName && w.ActionName == actionName));

        if (isUserAllowed) return;

        SystemLogger.Warn($"Access Error: User {currentUser.Id} was not allowed to access {controllerName}/{actionName}");

        var resultView = new ViewResult
        {
            ViewName = "~/Views/Error/AccessDenied.cshtml",
            TempData =
            {
                ["controllerName"] = controllerName,
                ["actionName"] = actionName,
                ["currentUser"] = currentUser.Detail.UserName
            }
        };

        filterContext.Result = resultView;
    }

    private static string GetControllerName()
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("controller"))
            return (string)routeValues["controller"];

        return string.Empty;
    }

    private static string GetActionName()
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("action"))
            return (string)routeValues["action"];

        return string.Empty;
    }

}

这两个过滤器都位于基本控制器上:

[CarParkAuthentication]
[CarParkAuthorization]
public class AsyncControllerBase : AsyncController { }

我的访问控制基于控制者/动作名称。数据库的映射设置如下:

DB Design

CarParkUser

public class CarParkUser : IPrincipal
{
    public CarParkUser(string userName, BDO.IntranetUserCarPark userDetail, IList<BDO.ParkingUserRole> roles)
    {
        Identity = new GenericIdentity(userName);
        Detail = userDetail;
        Roles = roles;
    }

    public IIdentity Identity { get; }

    public int Id => Detail.IntranetUserId;

    public BDO.IntranetUserCarPark Detail { get; }

    public IList<BDO.ParkingUserRole> Roles { get; }

    public bool IsInRole(string role) => Roles != null && Roles.Any(where => where.RoleName == role);

}

因此,使用此设置,我遇到了ERR_TOO_MANY_REDIRECTS错误。我想要的结果是:

  • 不是“ Mawgif”角色的所有用户都可以正常访问所有站点
  • Mawgif角色用户只能访问Mawgif控制器及其操作以及来自另一个控制器的一个操作。这些操作已在数据库中定义,可以从用户对象locations
  • 中获得

据我所知,我已经做了很多事情。我在这里对IAuthenticationFilter的理解也很有限。任何指针/帮助将不胜感激。

0 个答案:

没有答案