Атрибут Authorize Asp.net MVC, перенаправление на пользовательскую страницу "без прав"
Asp.net MVC2 перенаправляет на страницу входа с response 302
, когда пользователь, прошедший проверку подлинности, не имеет прав.
Я хотел бы разделить на два действия
- Если пользователь не аутентифицирован, то сделайте то, что он делает, переадресуйте на страницу входа.
- Если пользователь аутентифицирован, но не имеет необходимых прав, верните соответствующий код статуса http и не покажите страницу прав на чужую страницу.
Есть ли способ сделать это? Или я делаю что-то неправильно с авторизацией и аутентификацией формы? Единственный способ, о котором я могу думать, - написать собственный атрибут authorize, который я хочу избежать.
Ответы
Ответ 1
Вы можете написать собственный атрибут фильтра следующим образом:
public class CustomAuthorizeAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.User.Identity == null || !filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectResult(System.Web.Security.FormsAuthentication.LoginUrl + "?returnUrl=" +
filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.RawUrl));
}
//Check user right here
if (userNotRight)
{
filterContext.HttpContext.Response.StatusCode = 302;
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
И используйте его в контроллере:
[CustomAuthorize]
public class HomeController : Controller
{
}
Ответ 2
Вы можете написать собственный атрибут authorize и в AuthorizeCore, если пользователь не аутентифицирован, возвратите HttpUnauthorizedResult, и если он аутентифицирован, но не выполняет роли, вы должны выполнить другие действия. Обратите внимание: если вы вернете код статуса 401, структура FormsAuthentication в конечном итоге перенаправит с 302 на страницу входа.
Ответ 3
Как указано в Настройка авторизации в ASP.NET MVC, вы можете подклассифицировать AuthorizeAttribute для перехвата аутентифицированного, но неавторизованного сценария и заменить результат перенаправлением.
Ответ 4
Внедрите пользовательский AuthorizeAttribute
и добавьте следующее переопределение. Основой является проверка подлинности пользователя, но не авторизация, а затем перенаправление на вашу собственную страницу "Отказано в доступе". Надеюсь, это поможет!
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
// Check if user is authenticated and if this action requires authorization
if (filterContext.HttpContext.User.Identity.IsAuthenticated
&& filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AuthorizeAttribute), true))
{
List<object> attributes = new List<object>(filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true));
attributes.AddRange(filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true));
// Check all authorzation attributes
foreach (var attribute in attributes)
{
var authAttribute = attribute as AuthorizeAttribute;
if (authAttribute != null)
{
if (!filterContext.HttpContext.User.IsInRole(authAttribute.Roles))
{
// User is not authorized so redirect to our access denied error page
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "area", "" },
{ "controller", "Error" },
{ "action", "AccessDenied" }
});
break;
}
}
}
}
}
Ответ 5
Подобно решениям, предложенным @hellangle и @Andreas, для решения этой проблемы я использовал следующий код:
public class CustomizedAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var userAuthInfo = GetUserAuthInfo();
if (!userAuthInfo.IsAuthenticated())
{
filterContext.Result = new RedirectResult(UrlToYourLoginPage);
return;
}
if (!userAuthInfo.IsAuthorized())
{
var result = new ViewResult {ViewName = "UnAuthorized"};
result.ViewBag.Message = "Sorry! You are not authorized to do this!";
filterContext.Result = result;
}
}
}
Конечно, вам необходимо внедрить класс информации авторизации пользователя и связанные с ним методы (GetUserAuthInfo, IsAuthenticated, IsAuthorized) в соответствии с вашими конкретными потребностями. Кроме того, View, названный 'UnAuthorized', должен быть помещен туда, где может найти двигатель MVC. Затем его можно использовать в классе контроллера (указывается в ответе @hellangle) или в методе действий:
[CustomizedAuthorizeAttribute]
public class TargetController : Controller
{
[CustomizedAuthorizeAttribute]
public ActionResult TargetAction()
{
// Your Code
}
}
Чтобы обеспечить различную стратегию управления доступом для различных классов контроллеров и методов действий, реализуется конструктор класса CustomizedAuthorizeAttribute, который принимает параметры (ы), представляющие информацию управления доступом, а затем соответствующим образом определяет класс CustomizedAuthorizeAttribute.