有没有一种简单的方法可以在MVC5中跨域实现单点登录 [英] Is there a simple way to implement Single Sign On across domains in MVC5

查看:287
本文介绍了有没有一种简单的方法可以在MVC5中跨域实现单点登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景:

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

  • account.ilovepandas.com
  • ilovepandas.com

使用ASP.Net Identity,MVC5中是否有一种简单的方法来实现共享登录,因此,如果用户登录到ilovepandas.com并转到account.ilovepandas.com,则该用户已经通过身份验证了? /p>

已经对该主题进行了研究,并且那里有一些相当复杂的解决方案,例如Thinktecture,OWIN授权服务器.我的希望是,由于MVC4-5对我们的Identity进行了大修,所以也许现在有一个更简单的解决方案,而我只是找不到.

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

解决方案

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服务器),或者使用任何其他工具来获得有效密钥.如果您需要建议,我构建了一个应用程序,您可以使用此处,如果您要生成该应用程序,则可以链接到它的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);

Scenario:

Two separate web projects, running om these domains:

  • account.ilovepandas.com
  • ilovepandas.com

Using ASP.Net Identity, is there a simple way in MVC5 to implement a shared login, so that if the user is logged in to ilovepandas.com and goes to account.ilovepandas.com, he will already be authenticated?

I have done research on the topic, and there are some quite complicated solutions out there, like Thinktecture, OWIN authorization server. My hope is, that since MVC4-5 gave us a big overhaul of Identity, maybe there is an easier solution now, that I have just not been able to find.

It would seem to me to be as simple as letting them share the auth-cookie.

解决方案

TL;DR: Assuming both apps share the same top-level domain, you can share the authentication cookie. Set the domain on the cookie, and share any keys necessary to decrypt it between the apps.

Here, I'm going to assume you're using FormsAuthentication.

1) Add the domain attribute to the authentication/forms section:

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

Note the leading period on the domain.

2) In order for both apps to be able to decrypt the cookie, you need to add a machineKey to both, and use the same validation and encryption keys:

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

You can use the machine key tool in IIS Manager (assuming you have access to the web server), or whatever other tool gets you valid keys. If you need a suggestion, I built an app you can use here, which links to it's Github project if you want to generate your own keys.

For completeness:

Here's the class that will generate valid keys:

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;
    }
}

And you would use something like this to get your keys:

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);

这篇关于有没有一种简单的方法可以在MVC5中跨域实现单点登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆