我正在创建一个自定义角色提供程序,并在我的控制器中设置了一个指定角色的Authorize属性,它可以正常工作,就像这样:
[Authorize(Roles="SuperAdmin")]
public class SuperAdminController : Controller
...
但是当用户没有访问该控制器的权限时,他将被重定向到登录页面。如何将其重定向到 "AcessDenied.aspx" 页面?
我正在创建一个自定义角色提供程序,并在我的控制器中设置了一个指定角色的Authorize属性,它可以正常工作,就像这样:
[Authorize(Roles="SuperAdmin")]
public class SuperAdminController : Controller
...
但是当用户没有访问该控制器的权限时,他将被重定向到登录页面。如何将其重定向到 "AcessDenied.aspx" 页面?
[AccessDeniedAuthorize(Roles="SuperAdmin")]
public class SuperAdminController : Controller
AccessDeniedAuthorizeAttribute.cs:
public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if(filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectResult("~/AcessDenied.aspx");
}
}
}
以下是基于eu-ge-ne的答案的解决方案。 我的解决方案能够正确地将用户重定向到登录页面,如果他们没有登录,但如果用户已经登录但未被授权查看该页面,则会将其重定向到拒绝访问页面。
[AccessDeniedAuthorize(Roles="SuperAdmin")]
public class SuperAdminController : Controller
AccessDeniedAuthorizeAttribute.cs:
public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectResult("~/Account/Logon");
return;
}
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectResult("~/Account/Denied");
}
}
}
AccountController.cs:
public ActionResult Denied()
{
return View();
}
Views/Account/Denied.cshtml: (Razor syntax)
@{
ViewBag.Title = "Access Denied";
}
<h2>@ViewBag.Title</h2>
Sorry, but you don't have access to that page.
[MyAuthorize(Roles="SuperAdmin",ViewName="AccessDenied")]
public class SuperAdminController : Controller
...
重定向并不总是最好的解决方案
使用标准的http代码 403:
return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
public string AccessDeniedViewName { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (filterContext.HttpContext.User.Identity.IsAuthenticated &&
filterContext.Result is HttpUnauthorizedResult)
{
if (string.IsNullOrWhiteSpace(AccessDeniedViewName))
AccessDeniedViewName = "~/Account/AccessDenied";
filterContext.Result = new RedirectResult(AccessDeniedViewName);
}
}
}
app.UseAuthentication();
app.UseAuthorization();
确保在使用 app.UseAuthorization(); 前先使用 app.UseAuthentication();
换句话说,先问“你是谁?”,然后再问“你有权在这里吗?”,而不是反过来。
关于Vic Alcazar的一个小更新, 在重定向中添加了请求URL的详细信息 这样就可以记录访问被拒绝的详细信息和访问者身份(如果需要)
public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
public string AccessDeniedViewName { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (filterContext.HttpContext.User.Identity.IsAuthenticated &&
filterContext.Result is HttpUnauthorizedResult)
{
if (string.IsNullOrWhiteSpace(AccessDeniedViewName))
AccessDeniedViewName = "~/Account/AccessDenied";
var requestUrl = filterContext.HttpContext.Request.Url;
filterContext.Result = new RedirectResult(String.Format("{0}?RequestUrl={1}", AccessDeniedViewName, requestUrl));
}
}
}
我在Vic的答案基础上进行了改进,使得我可以为每个应用程序区域设置不同的Access Denied页面。这是通过返回一个RedirectToRouteResult
实现的,该结果不会将重定向到与应用程序根路径相关的URL,而是将其重定向到当前区域的控制器和操作:
public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
public string AccessDeniedController { get; set; }
public string AccessDeniedAction { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (filterContext.HttpContext.User.Identity.IsAuthenticated &&
filterContext.Result is HttpUnauthorizedResult)
{
if (String.IsNullOrWhiteSpace(AccessDeniedController) || String.IsNullOrWhiteSpace(AccessDeniedAction))
{
AccessDeniedController = "Home";
AccessDeniedAction = "AccessDenied";
}
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { Controller = AccessDeniedController, Action = AccessDeniedAction }));
}
}
}
public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (filterContext.Result is HttpUnauthorizedResult && WebSecurity.IsAuthenticated)
{
filterContext.Result = new RedirectResult("~/Account/AccessDenied");
}
}
}