是否有一种简单的方法可以在MVC5中跨域实现单点登录

时间:2015-06-06 21:55:44

标签: asp.net-mvc-5 owin

场景:

两个单独的Web项目,运行这些域:

  • account.ilovepandas.com
  • ilovepandas.com

使用ASP.Net Identity,在MVC5中有一种简单的方法来实现共享登录,这样如果用户登录到ilovepandas.com并转到account.ilovepandas.com,他将已经过身份验证吗? / p>

已经对该主题进行了研究,并且有一些非常复杂的解决方案,如Thinktecture,OWIN授权服务器。我的希望是,由于MVC4-5给了我们一个大的身份改革,也许现在有一个更简单的解决方案,我一直无法找到。

在我看来,就像让他们分享auth-cookie一样简单。

1 个答案:

答案 0 :(得分:2)

TL; DR:假设两个应用共享同一个顶级域名,您可以共享身份验证Cookie。在cookie上设置域,并共享在应用程序之间解密所需的任何密钥。

在这里,我将假设您正在使用FormsAuthentication。

1)将domain属性添加到authentication/forms部分:

<authentication mode="Forms">
  <forms loginUrl="~/account/login"
         timeout="2880"
         defaultUrl="~/"
         slidingExpiration="true"
         protection="All"
         domain=".yourdomain.tld"
         name="YOUR_COOKIE_NAME" />

请注意域名的结束时段。

2)为了让两个应用程序能够解密cookie,您需要向两者添加machineKey,并使用相同的验证和加密密钥:

<machinekey compatibilitymode="Framework45"
            validation="HMACSHA256"
            validationkey="YOURVALIDATIONKEYHERE"
            decryption="AES"
            decryptionkey="YOURDECRYPTIONKEYHERE" />

您可以在IIS管理器中使用计算机密钥工具(假设您可以访问Web服务器),或者使用其他任何工具获取有效密钥。如果您需要建议,我构建了一个可以使用here的应用程序,如果您想要生成自己的密钥,可以链接到它的Github项目。

完整性:

这是将生成有效密钥的类:

public class KeyGenerator
{
    public string GenerateKey(int length, bool useUpperCase = true)
    {
        byte[] buffer = new byte[length];
        var randomNumberGenerator = new RNGCryptoServiceProvider();
        randomNumberGenerator.GetBytes(buffer);

        return ToHexString(buffer, true);
    }

    private static string ToHexString(byte[] bytes, bool useUpperCase = false)
    {
        var hex = string.Concat(bytes.Select(b => b.ToString(useUpperCase ? "X2" : "x2")));

        return hex;
    }
}

你会用这样的东西拿到你的钥匙:

var generator = new KeyGenerator();

/* 512 bits = 64 bytes (512 / 8) */
string validationKey = generator.GenerateKey(64);

/* 256 bits = 32 bytes (256 / 8) */
string decryptionKey = generator.GenerateKey(32);