mvc5全局身份验证检查为什么不追加返回URL

时间:2015-10-11 19:27:24

标签: .net asp.net-mvc asp.net-mvc-routing simplemembership

我想对应用程序中的每个操作方法使用身份验证,因此我将其添加为FilterConfig.cs中的全局过滤器我不会在控制器级别或任何操作级别上使用任何 [授权] 属性。如果我将身份验证放在控制器和操作级别上,我会返回url但是当我将授权放在全局级别时,我得不到任何返回URL

在我的MVC项目中

web.config设置如下:

<authentication mode="Forms">
  <forms name="DemoApplication" loginUrl="~/Account/Login" timeout="2880" protection="All" />
</authentication>

FilterConfig语法如下:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new AuthorizationFilterAttribute());
        }

AuthorizationFilterAttribute继承 AuthorizeAttribute 类并覆盖以下方法

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {

            if (!HttpContext.Current.User.Identity.IsAuthenticated)
                filterContext.Result = new RedirectResult("~/Account/Login");

        }

上面的代码确保如果用户未经过身份验证,它将被重定向到forms元素的LoginUrl属性中定义的登录页面。在重定向期间,FormsAuthentication为什么不追加返回url

AccountController登录语法如下

[AllowAnonymous]


public ViewResult Login(string returnUrl)
    {
        //return View();
        //So that the user can be referred back to where they were when they click logon
        if (string.IsNullOrEmpty(returnUrl) && Request.UrlReferrer != null)
            returnUrl = Server.UrlEncode(Request.UrlReferrer.PathAndQuery);

        if (Url.IsLocalUrl(returnUrl) && !string.IsNullOrEmpty(returnUrl))
        {
            ViewBag.ReturnURL = returnUrl;
        }
        return View();
    }

注意:此处returnUrl始终为null

[AcceptVerbs(HttpVerbs.Post)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
    Justification = "Needs to take same parameter type as Controller.Redirect()")]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        authProvider.SignIn(model.UserName, false);

        if (!String.IsNullOrEmpty(returnUrl))
        {
            if (!String.IsNullOrEmpty(returnUrl.Replace("Account", "")))
            {
                return Redirect(returnUrl);
            }
        }
        //BuildUserSession(userName);
        return RedirectToAction("Index", "Home");
    }
    else
    {
        return View();
    }
} 

贝娄是我的观点部分

@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()
                <h4>Use a local account to log in.</h4>
                <hr />
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                <div class="form-group">
                    @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
                    <div class="col-md-10">
                        @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <div class="checkbox">
                            @Html.CheckBoxFor(m => m.RememberMe)
                            @Html.LabelFor(m => m.RememberMe)
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Log in" class="btn btn-default" />
                    </div>
                </div>

            }

2 个答案:

答案 0 :(得分:0)

确保在视图页面中包含returnUrl。

@using (Html.BeginForm("Login", "Account", new { returnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
}

答案 1 :(得分:0)

您的方法存在几个问题:

  1. HandleUnauthorizedRequest中,您无需检查用户是否经过身份验证。该支票为already done in AuthorizeCore
  2. 您正在直接重定向到登录页面,不允许表单身份验证附加重定向URL。正确的方法是return a HTTP 401 not authorized response,而不是重定向到网址。
  3. 默认AuthorizeAttribute已经为您完成了这两件事。在这种情况下,没有理由使用自定义授权过滤器。
  4. 因此,如果您按如下方式更改代码,它将像您期望的那样工作。

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new AuthorizeAttribute());
    }