我正在为我的网站编写登录功能。当用户请求使用[CustomAuthorize]
属性限制的视图时,会将用户正确地重定向到/Login/Index
视图,并附加查询字符串(?ReturnUrl=%2fRestricted%2fView
)。
但这是问题......
当用户尝试登录时,出现验证错误。发布请求会导致回发(duh),并且附加的查询字符串将从Url中消失。
CustomAuthorize.cs:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.User.Identity.IsAuthenticated)
{
var customIdentity = (CustomIdentity)httpContext.User.Identity;
var customPrincipal = new CustomPrincipal(customIdentity);
if (customIdentity.IsAdmin)
{
httpContext.User = customPrincipal;
Thread.CurrentPrincipal = customPrincipal;
}
}
return base.AuthorizeCore(httpContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var urlRequested = filterContext.HttpContext.Request.Path;
//urlRequested contains "/Restricted/View"
//Do something with 'urlRequested' here, or?
base.HandleUnauthorizedRequest(filterContext);
}
}
登录/索引视图
<body>
@using (Html.BeginForm("Index", "Login"))
{
<div>
@Html.LabelFor(model => model.UserName)
</div>
<div>
@Html.EditorFor(model => model.UserName)
@Html.ValidationMessageFor(model => model.UserName)
</div>
<div>
@Html.LabelFor(model => model.Password)
</div>
<div>
@Html.EditorFor(model => model.Password)
@Html.ValidationMessageFor(model => model.Password)
</div>
<div>
@Html.LabelFor(model => model.RememberMe)
</div>
<div>
@Html.EditorFor(model => model.RememberMe)
@Html.ValidationMessageFor(model => model.RememberMe)
</div>
<p>
<input type="submit" value="Login!" />
</p>
@Html.ValidationSummary(true)
}
</body>
登录/索引控制器操作:
[HttpPost]
public ActionResult Index(LoginModelBinding login, string returnUrl)
{
if (ModelState.IsValid)
{
if (Service.CheckUser(login.UserName, login.Password))
{
String loginError;
CustomAuthorization.Login(login.UserName, login.Password, out loginError);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
return RedirectToAction("Index", "MitTeam");
}
ModelState.AddModelError("", "The entered user name or password is incorrect");
}
return View(login);
}
解: 根据Naveen的回答,我修改了这样的代码:
public static void SaveReturnUrl(this Controller controller, string returnUrl, bool showAfterRedirect = true)
{
if (showAfterRedirect)
{
controller.TempData["returnUrl"] = returnUrl;
}
else
{
controller.ViewData["returnUrl"] = returnUrl;
}
}
public static string RetrieveReturnUrl(this Controller controller)
{
var message = controller.ViewData.ContainsKey("returnUrl") ? controller.ViewData["returnUrl"] : controller.TempData.ContainsKey("returnUrl") ? controller.TempData["returnUrl"] : null;
return message as string;
}
使用这两种扩展方法,我可以在Login Controller方法/操作中保存和检索returnurl。
登录发布方法:
var previousReturnUrl = this.RetrieveReturnUrl();
if(!ModelState.IsValid)
{
if(string.IsNullOrEmpty(previousReturnUrl))
{
this.SaveReturnUrl(returnUrl);
}
return View(login);
}
如果模型状态有效,我只需调用this.RetrieveReturnUrl
并对其进行解码,这样我就可以在成功登录时重定向用户。
答案 0 :(得分:1)
您可以使用Martijn Boland - Keep your users informed开发的代码模块。它可用于存储任何对象,并在重定向后将其提取回来。它专门用于在POST-REDIRECT操作后显示操作的消息或状态。这也适用于AJAX类型的请求。
在进行重定向后,您可以使用相同的方法存储返回URL以及消息(包含auth失败)。
答案 1 :(得分:0)
您可以在视图中将returnURL存储在隐藏字段中。只要您在回发到服务器的表单中包含该隐藏字段,您的POST操作就可以访问并使用它,具体取决于操作的结果(登录成功 - >重定向到URL,登录失败 - &gt;再次使用隐藏字段返回登录视图。