使用自定义 AuthorizeAttribute 生成 return Url
Generate a return Url with a custom AuthorizeAttribute
我有一个自定义授权属性:
using System;
using System.Web.Mvc;
using System.Web.Routing;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Login", action = "Login" }));
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
...我用来装饰某些控制器的:
[MyAuthorizeAttribute(Roles = "Superman, Batman, Spiderman")]
public class SuperHeroController : Controller
{
// ....
}
任何人都可以解释一下如何修改授权代码,以便在授权失败时登录 URL 包含一个 ReturnUrl
(当前 controller/method 的 URL) ?
这基本上是在尝试模仿 Web 表单 ReturnUrl 逻辑,但采用了一种巧妙的方式,因此我不必为 URL.
手动使用字符串
终于弄明白了,尽管有人可能会提出更好的方法...
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Login",
action = "Login",
returnUrl = filterContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped)
}));
尽管看起来略有不同,但这正是我解决同一问题所需要的:
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", "Account" },
{ "action", "Login" },
{ "returnUrl", filterContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped) }
});
谢谢!
有很多方法可以实现这一点。
您应该使用 filterContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped)
来获取 returnUrl。
第一种方式:
var returnUrl = filterContext.HttpContext.Request.Url?.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped) ?? "";
if (!string.IsNullOrWhiteSpace(returnUrl))
{
returnUrl = "/" + returnUrl;
}
filterContext.Result = new RedirectResult($"~/Login/Login{returnUrl}");
第二种方式:
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Login",
action = "Login",
area = "",
returnUrl = filterContext.HttpContext.Request.Url?.GetComponents(UriComponents.PathAndQuery,
UriFormat.SafeUnescaped)
}));
只是,别忘了设置区域。
我有一个自定义授权属性:
using System;
using System.Web.Mvc;
using System.Web.Routing;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Login", action = "Login" }));
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
...我用来装饰某些控制器的:
[MyAuthorizeAttribute(Roles = "Superman, Batman, Spiderman")]
public class SuperHeroController : Controller
{
// ....
}
任何人都可以解释一下如何修改授权代码,以便在授权失败时登录 URL 包含一个 ReturnUrl
(当前 controller/method 的 URL) ?
这基本上是在尝试模仿 Web 表单 ReturnUrl 逻辑,但采用了一种巧妙的方式,因此我不必为 URL.
手动使用字符串终于弄明白了,尽管有人可能会提出更好的方法...
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Login",
action = "Login",
returnUrl = filterContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped)
}));
尽管看起来略有不同,但这正是我解决同一问题所需要的:
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", "Account" },
{ "action", "Login" },
{ "returnUrl", filterContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped) }
});
谢谢!
有很多方法可以实现这一点。
您应该使用 filterContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped)
来获取 returnUrl。
第一种方式:
var returnUrl = filterContext.HttpContext.Request.Url?.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped) ?? "";
if (!string.IsNullOrWhiteSpace(returnUrl))
{
returnUrl = "/" + returnUrl;
}
filterContext.Result = new RedirectResult($"~/Login/Login{returnUrl}");
第二种方式:
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Login",
action = "Login",
area = "",
returnUrl = filterContext.HttpContext.Request.Url?.GetComponents(UriComponents.PathAndQuery,
UriFormat.SafeUnescaped)
}));
只是,别忘了设置区域。