本质上,当某人不属于我的属性中列出的角色时,我想显示一条友好的消息。目前我的应用程序只是将用户吐回登录屏幕。我已经阅读了一些关于创建仅扩展 [AuthorizeAttribute] 的自定义属性的帖子,但我认为必须有一些开箱即用的东西才能做到这一点?
有人可以请我指出我需要寻找的正确方向,不要让它将用户发送到登录表单,而只是向他们发送“未授权”消息?
本质上,当某人不属于我的属性中列出的角色时,我想显示一条友好的消息。目前我的应用程序只是将用户吐回登录屏幕。我已经阅读了一些关于创建仅扩展 [AuthorizeAttribute] 的自定义属性的帖子,但我认为必须有一些开箱即用的东西才能做到这一点?
有人可以请我指出我需要寻找的正确方向,不要让它将用户发送到登录表单,而只是向他们发送“未授权”消息?
我添加 $0.02 可能有点晚,但是当您创建 CustomAuthorizationAttribue 时,您可以使用AuthorizationContext.Result 属性来指示 AuthorizeAttribute.HandleUnauthorizedRequest 方法将用户引导到何处。
这是一个非常简单的示例,允许您指定在授权失败后应将用户发送到的 URL:
public class Authorize2Attribute : AuthorizeAttribute
{
// Properties
public String RedirectResultUrl { get; set; }
// Constructors
public Authorize2Attribute()
: base()
{
}
// Overrides
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (String.IsNullOrEmpty(RedirectResultUrl))
base.HandleUnauthorizedRequest(filterContext);
else
filterContext.Result = new RedirectResult(RedirectResultUrl);
}
}
如果我想按照上一篇文章中的建议将用户重定向到 /Error/Unauthorized :
[Authorize2(Roles = "AuthorizedUsers", RedirectResultUrl = "/Error/Unauthorized")]
public ActionResult RestrictedAction()
{
// TODO: ...
}
几天前我遇到了这个问题,解决方案有点详细,但这里是重要的部分。在AuthorizeAttribute
该OnAuthorization
方法中,HttpUnauthorizedResult
当授权失败时返回一个,这使得返回自定义结果有点困难。
我最终做的是创建一个 CustomAuthorizeAttribute 类并重写 OnAuthorization 方法以引发异常。然后,我可以使用自定义错误处理程序捕获该异常并显示自定义错误页面,而不是返回 401(未授权)。
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public virtual void OnAuthorization(AuthorizationContext filterContext) {
if (filterContext == null) {
throw new ArgumentNullException("filterContext");
}
if (AuthorizeCore(filterContext.HttpContext)) {
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else {
// auth failed, redirect to login page
// filterContext.Result = new HttpUnauthorizedResult();
throw new HttpException ((int)HttpStatusCode.Unauthorized, "Unauthorized");
}
}
}
然后在您的 web.config 中,您可以为特定错误设置自定义处理程序:
<customErrors mode="On" defaultRedirect="~/Error">
<error statusCode="401" redirect="~/Error/Unauthorized" />
<error statusCode="404" redirect="~/Error/NotFound" />
</customErrors>
然后实现你自己的 ErrorController 来提供自定义页面。
在 IIS7 上,您需要查看设置Response.TrySkipIisCustomErrors = true;
以启用您的自定义错误。
如果您想要简单或完全控制逻辑,则可以在您的操作方法中调用它:
User.IsInRole("NameOfRole");
它返回一个布尔值,您可以根据该结果执行其余的逻辑。
我在某些情况下使用的另一个是:
System.Web.Security.Roles.GetRolesForUser();
我认为这会返回一个字符串 [],但不要引用我的话。
编辑: 一个例子总是有帮助......
public ActionResult AddUser()
{
if(User.IsInRoles("SuperUser")
{
return View("AddUser");
}
else
{
return View("SorryWrongRole");
}
}
只要您的返回类型是“ActionResult”,您就可以返回任何可接受的返回类型(ViewResult、PartialViewResult、RedirectResult、JsonResult...)
与crazyarabian 非常相似,但如果用户实际经过身份验证,我只会重定向到我的字符串。如果他们当前未登录,这允许属性重定向到标准登录页面,但如果他们没有访问 url 的权限,则可以重定向到另一个页面。
public class EnhancedAuthorizeAttribute : AuthorizeAttribute
{
public string UnauthorizedUrl { get; set; }
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var redirectUrl = UnauthorizedUrl;
if (filterContext.HttpContext.User.Identity.IsAuthenticated && !string.IsNullOrWhiteSpace(redirectUrl))
{
filterContext.Result = new RedirectResult(redirectUrl);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
开箱即用的行为是 [Authorize] 属性返回 HTTP 401。FormsAuthenticationModule(默认加载)拦截此 401 并将用户重定向到登录页面。看看 System.Web.Security.FormsAuthenticationModule::OnLeave in Reflector 看看我的意思。
如果您希望 AuthorizeAttribute 执行除返回 HTTP 401 以外的操作,则必须覆盖 AuthorizeAttribute::HandleUnauthorizedRequest 方法并在其中执行您的自定义逻辑。或者,只需更改 ~\Web.config 的这一部分:
<forms loginUrl="~/Account/LogOn" timeout="2880" />
并使其指向不同的 URL,例如 ~/AccessDenied。