跨域身份验证ASP.net MVC

时间:2015-07-30 10:17:25

标签: c# asp.net asp.net-mvc-4 authentication cross-domain

我有两个使用ASP.net MVC构建的不同Web应用程序。这两个应用程序可能无法在同一服务器上运行,也不能在同一域中运行。

我想如果用户登录其中一个,则应自动登录另一个。同样适用于注销。

您认为哪种解决方案最好?你知道一些示例代码吗?

谢谢!

---更多信息编辑---

用例场景:

用户在标签页上打开了网络应用程序A ,并且在应用程序的某个位置有一个链接可将用户重定向到 Web应用程序B 。如果他登录 A ,我想向他显示整页,如果不是,请将他重定向到登录表单。

为什么我需要这样做:

已构建应用 A B 。显然,访问 B 的唯一方法是点击 A 中的链接,只有在您之前已登录时才会显示该链接。问题是,如果您知道 B 某些页面的网址(很长且很复杂,但仍然存在),您可以在浏览器上将其写入并访问 B ,意味着安全问题。

6 个答案:

答案 0 :(得分:8)

我的答案可能不是最好的答案,但你可以使用一些棘手的机制,如

  1. 每当您使用其他应用程序时,您需要将一个令牌从应用程序A传递到B.
  2. 在B网站上验证此令牌。
  3. 并根据令牌授权该用户。 (我的意思是申请沉默或后门登录)

答案 1 :(得分:6)

我假设您无法使用任何共享存储在应用程序A和B之间进行通信。 (这可能允许一些共享会话实现)。

这样做的行业标准方式(OpenID Connect)就像其他一些答案所暗示的那样。我会尝试提供更多细节,以帮助您走上正确的轨道。

应用程序A和B都应该将身份验证过程中继到受信任的第三方(可以使用A,B或其他应用程序托管) - 让我们称之为C

当用户到达A或B时(无论B有奇怪的复杂URL,她总能将这些URL加入书签),他的请求应包含授权令牌。如果没有,她没有经过身份验证,将被重定向到C并提供一些登录机制 - 比如用户/传递表单。

成功登录后,她将被重定向回A / B(取决于她来自哪里),以完成她使用身份验证令牌所做的事情。现在,拥有身份验证令牌,她已通过身份验证。

如果她使用A进行身份验证,然后重定向到B,则此重定向也应包含令牌,B将知道如何信任该令牌。

现在,如果他只是打开一个新标签,B就不会看到任何标记,所以她会被重定向到C,只是被重定向回来(她已经过身份验证,还记得吗?)给B带有令牌,现在一切都很好。

我所描述的是使用OpenID连接的常见流程,如果使用.net,我真的建议使用Thinktecture的IdentityServer为您做好工作并成为您的“C”。

另一种选择是支付托管为SaaS应用程序的“C” - 查看Auth0

答案 2 :(得分:5)

您可以在A Project中实施OAuth。您可以在此处获得更多帮助:http://www.openauthentication.org/about

答案 3 :(得分:5)

答案 4 :(得分:4)

我认为你所追求的是CAS(中央认证服务) https://en.wikipedia.org/wiki/Central_Authentication_Service

有许多CAS提供商可用。我建议你查看https://wiki.jasig.org/display/CAS/Home

  

它将为您提供启用的现成解决方案的数量   用特定语言或基于框架编写的Web服务,   使用CAS。这将有助于您实现SSO解决方案   几个小时

答案 5 :(得分:4)

感谢 @Kaushik Thanki 的回答,我已经实现了一些修复我的问题的代码。我将在这里发布它适用于我的解决方案,即使它不是优化。

首先,我已经在 A 中实施了一个方法来向 B 发出帖子请求。在这个方法中,我获取用户的id,并使用其他一些参数和密码对其进行哈希。然后,我发送 B 用户ID,哈希值和布尔值,以便在登录和注销之间进行选择。

private void SendPostRequest(bool login)
        {
            // Create the combine string
            string data = // userId combined with more stuff

            // Create the hash of the combine string
            HashAlgorithm algorithm = MD5.Create();
            byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(data));
            StringBuilder sb = new StringBuilder();
            foreach (byte b in hash)
                sb.Append(b.ToString("X2"));

            string encriptedData = sb.ToString();

            // Fill the url with the path and the data
            string url = "http://localhost/xxx/yyy/ExternalAuthentication/Login?id=" + _cachedCustomer.Id + "&hash=" + encriptedData + "&login=" + login.ToString();

            // Make the Post request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream resStream = response.GetResponseStream();
        }

之后,我在 B 中创建了一个新类来处理登录逻辑。我使用 HttpContext.Current.Application 变量来存储身份验证的状态:

public class ExternalAuthenticationController : Controller
        {

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

            public ActionResult Login(string id, string hash, string login)
            {
               // Create the combine string
               string data = //user id + same stuff than in A;

               // Create the hash of the combine string
               HashAlgorithm algorithm = MD5.Create();
               byte[] hashArray =    algorithm.ComputeHash(Encoding.UTF8.GetBytes(data));
               StringBuilder sb = new StringBuilder();
               foreach (byte b in hashArray)
                  sb.Append(b.ToString("X2"));
               string originalHash = sb.ToString();

               // Compare the two hash. If they are the same, create the variable
               if (hash.CompareTo(originalHash) == 0)
               {

               if (System.Web.HttpContext.Current.Application["Auth"] == null)
               {
                   System.Web.HttpContext.Current.Application["Auth"] = false;
               }

               if (Convert.ToBoolean(login))
               {
                   System.Web.HttpContext.Current.Application["Auth"] = true;
               }

              else
              {
                  System.Web.HttpContext.Current.Application["Auth"] = false;
              }
             }
         }

可能 @vijay shiyani 提供的答案更好,更通用,但从我的观点来看,需要花费大量时间来实现它。