【问题标题】:Auto-redirect not working after user authentication用户身份验证后自动重定向不起作用
【发布时间】:2015-08-12 13:52:17
【问题描述】:

我和我的团队正在 ASP .NET 5 中启动一个新的网站项目,我正在尝试建立我们的用户身份验证和授权策略的基础。

我目前正在为返回用户使用基于 cookie 的身份验证,因此我在 Startup.cs 的 Configure 方法中添加了以下内容:

        // Redirect to login page if user is not logged in.
        app.UseCookieAuthentication(options =>
        {
            options.AutomaticAuthentication = true;
            options.ExpireTimeSpan = new System.TimeSpan(0, 1, 0);
            options.SlidingExpiration = true;
            options.LoginPath = "/Login";
            options.ReturnUrlParameter = "ReturnUrl";
        });

身份验证服务也添加到 ConfigureServices 方法中。

我担心的是 LoginPath 参数:当我的中间件/过滤器(我都尝试过)返回 401 代码时,自动重定向到登录页面正常工作,但从登录页面自动重定向回最初请求的页面不会'不起作用:即使在成功登录后,浏览器仍保留在登录页面上。

我强烈怀疑问题出在我的控制器的某个地方。这是它的(稍微简化的)源代码:

[Route("[controller]")]
[AllowAnonymous]
public class LoginController : Controller
{
    private static readonly string AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme;

    public IActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public async System.Threading.Tasks.Task<ActionResult> Post(LoginInfo infos)
    {
        if (ValidateLogin(infos))
        {
            await Context.Authentication.SignInAsync(AuthenticationScheme, new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
            {
                new Claim(ClaimTypes.Role, "Admin")
            }, 
            AuthenticationScheme)));
        }

        return View("Index");
    }

    private static bool ValidateLogin(LoginInfo infos)
    {
        return infos.Username == "abc" && infos.Password == "def";
    }
}

(为了清楚起见,删除了一些代码,例如,如果用户名/密码组合被拒绝,则显示错误消息)

视图非常简单,包含一个简单的表单,提供几个编辑框并将用户/密码 POST 到控制器(再次,为清楚起见,删除了错误消息):

@using (Html.BeginForm("Post", "Login", FormMethod.Post))
{
    <div>
        <h2>Login Page</h2>
        <p>
            @Html.Label("Username")
            @Html.Editor("Username")
        </p>

        <p>
            @Html.Label("Password")
            @Html.Password("Password")
        </p>

        <p>
            <input type="submit" value="Attempt login" />
        </p>
    </div>
}

我已经能够通过在单独的控制器中获取用户身份和声明来检查用户登录是否正常工作。到登录页面的初始重定向也可以正常工作(即,当我尝试在不登录的情况下访问网站的受保护部分时,我被重定向到“/Login”),并且重定向的 URL 正确包含 ReturnUrl 查询参数。我还尝试在处理 Post 操作时访问 Referer URL,并通过从控制器手动返回 RedirectResult 来强制触发重定向,因此 ReturnUrl 本身的内容也必须是好的。

那么...谁能帮我理解为什么重定向到返回 URL 不会自动执行?

编辑:根据 CookieAuthenticationOptions.LoginPath 的文档:

总结: LoginPath 属性通知中间件它应该更改传出的 401 未经授权的状态代码转换为 302 重定向到给定的登录路径。 生成 401 的当前 url 作为查询添加到 LoginPath 由 ReturnUrlParameter 命名的字符串参数。 一旦请求到 LoginPath 授予新的 SignIn 身份,ReturnUrlParameter 值用于重定向 浏览器返回导致原始未授权状态码的url。 如果 LoginPath 为 null 或为空,则中间件不会查找 401 Unauthorized 状态码,登录时不会自动重定向。

粗体部分是我正在尝试利用的部分...重定向到静态页面(即手动将 Redirect() 返回到某个硬编码页面)不是我在这里想要完成的。

【问题讨论】:

  • ReturnUrlParameter为空时,框架怎么知道重定向到哪里?
  • 您可以在登录后尝试访问受保护的资源看看会发生什么吗?
  • 你可以试试:HttpContext.GetOwinContext() 而不是Context
  • 我不知道为什么Context 有效,但是看看这个问题,看起来我们必须使用HttpContext.GetOwinContext()stackoverflow.com/questions/26287634/…
  • 实际登录工作正常:在控制器登录某人之前,受保护的资源不可用。关于 OwinContext,我的控制器似乎无法访问任何类似的东西。我想这是 ASP 5 / MVC 6 中发生的许多变化之一。到目前为止,我发现的大多数代码示例和 SO 问题都涉及不再存在或已重命名的类和/或属性。

标签: c# asp.net-core asp.net-core-mvc


【解决方案1】:

问题是您在成功登录后总是返回索引视图:

[HttpPost]
public async System.Threading.Tasks.Task<ActionResult> Post(LoginInfo infos)
{
        if (ValidateLogin(infos))
        {
            await Context.Authentication.SignInAsync(AuthenticationScheme, new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
            {
                new Claim(ClaimTypes.Role, "Admin")
            }, 
            AuthenticationScheme)));
        }

        return View("Index"); //the problem is here
}

尝试将return View("Index"); 替换为您希望将用户重定向到的视图(可能在另一个控制器上)。你可以试试RedirectToAction:Redirect to Action in another controller。比如:

return RedirectToAction("Index", "Home");

在您的情况下,如果您依赖框架为您进行重定向,请尝试:

[HttpPost]
public async System.Threading.Tasks.Task Post(LoginInfo infos)
{
        if (ValidateLogin(infos))
        {
            await Context.Authentication.SignInAsync(AuthenticationScheme, new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
            {
                new Claim(ClaimTypes.Role, "Admin")
            }, 
            AuthenticationScheme)));
        }
 }

【讨论】:

    猜你喜欢
    • 2016-11-04
    • 2013-11-15
    • 2018-03-26
    • 1970-01-01
    • 2011-12-19
    • 2016-08-08
    • 2019-01-23
    • 2015-07-13
    • 1970-01-01
    相关资源
    最近更新 更多