我有两个使用ASP.net MVC构建的不同Web应用程序。这两个应用程序可能无法在同一服务器上运行,也不能在同一域中运行。
我想如果用户登录其中一个,则应自动登录另一个。同样适用于注销。
您认为哪种解决方案最好?你知道一些示例代码吗?
谢谢!
---更多信息编辑---
用例场景:
用户在标签页上打开了网络应用程序A ,并且在应用程序的某个位置有一个链接可将用户重定向到 Web应用程序B 。如果他登录 A ,我想向他显示整页,如果不是,请将他重定向到登录表单。
为什么我需要这样做:
已构建应用 A 和 B 。显然,访问 B 的唯一方法是点击 A 中的链接,只有在您之前已登录时才会显示该链接。问题是,如果您知道 B 某些页面的网址(很长且很复杂,但仍然存在),您可以在浏览器上将其写入并访问 B ,意味着安全问题。
答案 0 :(得分:8)
我的答案可能不是最好的答案,但你可以使用一些棘手的机制,如
答案 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)
OWIN OAuth 2.0授权服务器 http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
答案 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 提供的答案更好,更通用,但从我的观点来看,需要花费大量时间来实现它。