不同域上的登录页面

时间:2014-01-22 06:03:29

标签: c# asp.net asp.net-mvc asp.net-mvc-5 owin

我对OWIN认证完全陌生,我必须误解一切是如何运作的,但我无法在任何地方找到这个。

我想要的是能够使用中央域进行身份验证。如果有人在未经过身份验证时尝试访问apps.domain.com,则会将其重定向到accounts.domain.com/login,以便将所有身份验证分成其自己的域和应用程序。使用MVC 4表单身份验证非常简单,您可以在其中指定完整的URL,但似乎不是OWIN。

Startup.Auth.cs

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    LoginPath = new PathString("/account/login")
}

使用CookieDomain选项设置Cookie时,可以轻松指定域。但是,当您指定要重定向到的登录路径时,它必须相对于当前应用程序,那么如何在MVC 4表单身份验证中完成哪些操作非常简单?

在没有深入了解OWIN身份验证的全部内容的情况下,经过几个小时的搜索后,我找不到任何解决此问题的方法。

2 个答案:

答案 0 :(得分:49)

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Active,
            LoginPath = new PathString("/account/login"),
            LogoutPath = new PathString("/account/logout"),
            Provider = new CookieAuthenticationProvider
            {
                OnApplyRedirect = ApplyRedirect
            },
        });
    }

    private static void ApplyRedirect(CookieApplyRedirectContext context)
    {
        Uri absoluteUri;
        if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, out absoluteUri))
        {
            var path = PathString.FromUriComponent(absoluteUri);
            if (path == context.OwinContext.Request.PathBase + context.Options.LoginPath)
            {
                context.RedirectUri = "http://accounts.domain.com/login" +
                    new QueryString(
                        context.Options.ReturnUrlParameter,
                        context.Request.Uri.AbsoluteUri);
            }
        }

        context.Response.Redirect(context.RedirectUri);
    }
}

如果apps.domain.com是唯一可能的返回网址,您应该强烈考虑将context.Request.Uri.AbsoluteUri替换为context.Request.PathBase + context.Request.Path + context.Request.QueryString并在您的身份验证服务器中构建一个绝对返回网址,以保护您的应用免受滥用重定向

希望这会有所帮助;)

编辑:您可能会问自己为什么我不使用context.RedirectUri属性直接应用重定向。事实上,ICookieAuthenticationProvider.ApplyRedirect负责多个重定向,对应于登录和注销流程(是的,我知道,它违反了单一责任原则......)。但更糟糕的是:context.RedirectUri可以在登录流程的开头表示身份验证端点的绝对URL,也可以在有效发送cookie时表示最终浏览器的目标(即真正的相对“返回URL”)回到浏览器...这就是为什么我们需要确保context.RedirectUri是绝对的并且对应于已注册的context.Options.LoginPath

答案 1 :(得分:5)

我正在研究https://github.com/IdentityServer/IdentityServer3的示例,我有不同的答案。在https://www.scottbrady91.com/Identity-Server/Identity-Server-3-Standalone-Implementation-Part-2的示例中,它们显示了一个使用独立IdP和cookie身份验证的MVC应用程序。这个例子并没有包括让401重定向工作,但我偶然发现了。

基本方案是在AccountController中创建一个用于登录的操作。

public ActionResult SignIn() {
  // set up some bookkeeping and construct the URL to the central auth service
  return Redirect(authURL);
}

现在您有一个可以在Startup中使用的本地URL

public class Startup {
  public void Configuration(IAppBuilder app) {
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
      AuthenticationType = "Cookies",
      LoginPath = new PathString("/Account/SignIn")
    });
}

您还可以获得额外的好处,即您可以在菜单栏上为SignIn设置一个操作链接,供那些想要在401之前登录的人使用。我们在这里所做的是将决定与当未经身份验证的用户从获取身份验证的方式询问资源时该怎么做。