如果用户属于特定角色,我希望有条件访问特定控制器。该用户无法访问其他任何内容。如果用户不是该特定角色的用户,则将其转到常规站点。
我为此有两个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 { }
我的访问控制基于控制者/动作名称。数据库的映射设置如下:
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
错误。我想要的结果是:
据我所知,我已经做了很多事情。我在这里对IAuthenticationFilter
的理解也很有限。任何指针/帮助将不胜感激。