我正在用子项目在 ASP.NET MVC 4 中实现一个应用程序,我希望这些应用程序共享相同的登录名(只需登录一个应用程序,无需登录子项目)。
使用 webForms,我们通常使用机器键来完成,但在 MVC 4 中它不再起作用了。在 MVC 4 中有什么新的解决方案吗?
我正在用子项目在 ASP.NET MVC 4 中实现一个应用程序,我希望这些应用程序共享相同的登录名(只需登录一个应用程序,无需登录子项目)。
使用 webForms,我们通常使用机器键来完成,但在 MVC 4 中它不再起作用了。在 MVC 4 中有什么新的解决方案吗?
由于这Forms authentication
是通过 Forms 身份验证完成的ticket
,如果所有应用程序共享一个身份验证票证,则用户只需登录一次,即单点登录。假设我们有两个具有这些 URL 的应用程序:
http://public.mysite.com/app1/default1.aspx
http://public.mysite.com/app2/default2.aspx
如您所见,它们基本上是同一子域下的两个虚拟目录 - app1public.mysite.com.
写入的 cookie将对app2可见,反之亦然。
但是,这并不意味着当用户登录app1 时,他会自动登录app2。原因是默认情况下,每个 ASP.NET 应用程序都使用自己的加密密钥来创建 Forms 身份验证票证和 cookie。因此,app1 写入的 cookie 无法被app2成功读取,即使它对app2可见。
我们如何才能让两个应用程序识别对方的身份验证票和cookie?
事实上,它在 ASP.NET 中非常简单。唯一需要做的是更改 web.config 文件元素中的设置。以下是 machinKey 的默认设置:
<machineKey
validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps"
validation="SHA1"
decryption="Auto"
/>
通过这些设置,.NET 框架使用自动生成的validationKey
和decrytionKey
创建身份验证票证和 cookie。每个应用程序使用不同的密钥。为了使多个应用程序共享相同的身份验证票证和 cookie,我们只需将所有应用程序中的validationKey
and设置decrytionKey
为相同的值。
为了生成密钥,使用RNGCryptoSErviceProvider
了命名空间中的类System.Security.Cryptography
,如以下代码示例所示:
public String CreateKey(int numBytes)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[numBytes];
rng.GetBytes(buff);
return BytesToHexString(buff);
}
private String BytesToHexString(byte[] bytes)
{
StringBuilder hexString = new StringBuilder(64);
for (int counter = 0; counter < bytes.Length; counter++)
{
hexString.Append(String.Format("{0:X2}", bytes[counter]));
}
return hexString.ToString();
}