跨域认证ASP.net MVC
Cross-domain authentication ASP.net MVC
我有两个使用 ASP.net MVC 构建的不同 Web 应用程序。这两个应用程序可能 运行 不在同一服务器或同一域中。
我希望如果用户登录其中一个,则应该自动登录另一个。同样适用于注销。
您认为哪个是最佳解决方案?您知道一些示例代码吗?
谢谢!
--- 编辑了更多信息 ---
用例场景:
用户在选项卡上打开了 web 应用程序 A,并且在应用程序的某个位置有一个 link 将用户重定向到 网络应用程序 B。如果他在 A 上登录,我想向他显示整个页面,如果他没有登录,则将他重定向到登录表单。
为什么我需要这样做:
应用程序 A 和 B 已经构建。显然,访问 B 的唯一方法是单击 A 中的 link,只有您之前登录过才会显示.问题是,如果您知道 B 的某个页面的 URL (又长又复杂,但仍然如此),您可以将其写在浏览器上并访问 B,表示安全问题
我想你追求的是CAS(Central Authentication Service)
https://en.wikipedia.org/wiki/Central_Authentication_Service
有许多可用的 CAS 提供程序。我建议你看看这个 https://wiki.jasig.org/display/CAS/Home
it will give you number of out-of-the-box solutions exist to enable
web services written in a specific language, or based on a framework,
to use CAS. This will help you implement a SSO solution in
a matter of hours
我的答案可能不是最好的,但是你可以使用一些棘手的机制,比如
- 无论何时您要进行另一个应用程序,您都需要将一个令牌从应用程序 A 传递到 B。
- 在 B 站点验证此令牌。
- 并根据令牌授权该用户。 (我的意思是应用静默或后门登录)
感谢 @Kaushik Thanki 的回答,我已经实现了一些代码来解决我的问题。我将 post 此处提供适合我的解决方案,即使它不是最佳选择。
首先,我在 A 中实现了一种向 B 发出 Post 请求的方法。在这个方法中,我获取了用户的 ID,并使用一些其他参数和密码对其进行了 hash。然后,我向 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 中创建了一个新的 class 来处理登录逻辑。我使用 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提供的答案更好更笼统,但从我的角度来看,它需要很多时间来实现。
您可以在一个项目中实现OAuth。您可以在这里获得更多帮助:http://www.openauthentication.org/about
OWIN OAuth 2.0 授权服务器
http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
我假设您无法使用任何共享存储在应用程序 A 和 B 之间进行通信。 (这可能允许一些共享会话实现)。
更符合行业标准的方式 (OpenID Connect) 就像其他一些答案所暗示的那样。我会尝试提供更多详细信息,让您走上正轨。
应用程序 A 和 B 都应将身份验证过程中继给受信任的第三方(可以托管在 A、B 或完全不同的应用程序中)- 我们称之为 C
当用户到达 A 或 B(无论 B 有奇怪的复杂 URL,她总是可以将它们添加为书签)时,他的请求应该包含一个授权令牌。如果没有,她就没有通过身份验证,将被重定向到 C 并提供一些登录机制 - 比如 user/pass 表单。
成功登录后,她将被重定向回 A/B(取决于她来自哪里)以完成她使用身份验证令牌所做的一切。现在,有了身份验证令牌,她就通过了身份验证。
如果她通过 A 的身份验证然后重定向到 B,则此重定向也应包含令牌,B 将知道如何信任该令牌。
现在,如果他只是打开一个新标签页,B 将看不到任何令牌,因此她将被重定向到 C,然后又被重定向回(她已经通过身份验证,还记得吗?)令牌,现在一切都很好。
我描述的是使用 OpenID 连接的常见流程,如果使用 .net,我真的建议使用 Thinktecture 的 IdentityServer 来为您完成艰苦的工作并成为您的 "C"。
另一种选择是为此类 "C" 托管为 SaaS 应用程序付费 - 查看 Auth0
我有两个使用 ASP.net MVC 构建的不同 Web 应用程序。这两个应用程序可能 运行 不在同一服务器或同一域中。
我希望如果用户登录其中一个,则应该自动登录另一个。同样适用于注销。
您认为哪个是最佳解决方案?您知道一些示例代码吗?
谢谢!
--- 编辑了更多信息 ---
用例场景:
用户在选项卡上打开了 web 应用程序 A,并且在应用程序的某个位置有一个 link 将用户重定向到 网络应用程序 B。如果他在 A 上登录,我想向他显示整个页面,如果他没有登录,则将他重定向到登录表单。
为什么我需要这样做:
应用程序 A 和 B 已经构建。显然,访问 B 的唯一方法是单击 A 中的 link,只有您之前登录过才会显示.问题是,如果您知道 B 的某个页面的 URL (又长又复杂,但仍然如此),您可以将其写在浏览器上并访问 B,表示安全问题
我想你追求的是CAS(Central Authentication Service) https://en.wikipedia.org/wiki/Central_Authentication_Service
有许多可用的 CAS 提供程序。我建议你看看这个 https://wiki.jasig.org/display/CAS/Home
it will give you number of out-of-the-box solutions exist to enable web services written in a specific language, or based on a framework, to use CAS. This will help you implement a SSO solution in a matter of hours
我的答案可能不是最好的,但是你可以使用一些棘手的机制,比如
- 无论何时您要进行另一个应用程序,您都需要将一个令牌从应用程序 A 传递到 B。
- 在 B 站点验证此令牌。
- 并根据令牌授权该用户。 (我的意思是应用静默或后门登录)
感谢 @Kaushik Thanki 的回答,我已经实现了一些代码来解决我的问题。我将 post 此处提供适合我的解决方案,即使它不是最佳选择。
首先,我在 A 中实现了一种向 B 发出 Post 请求的方法。在这个方法中,我获取了用户的 ID,并使用一些其他参数和密码对其进行了 hash。然后,我向 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 中创建了一个新的 class 来处理登录逻辑。我使用 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提供的答案更好更笼统,但从我的角度来看,它需要很多时间来实现。
您可以在一个项目中实现OAuth。您可以在这里获得更多帮助:http://www.openauthentication.org/about
OWIN OAuth 2.0 授权服务器 http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
我假设您无法使用任何共享存储在应用程序 A 和 B 之间进行通信。 (这可能允许一些共享会话实现)。
更符合行业标准的方式 (OpenID Connect) 就像其他一些答案所暗示的那样。我会尝试提供更多详细信息,让您走上正轨。
应用程序 A 和 B 都应将身份验证过程中继给受信任的第三方(可以托管在 A、B 或完全不同的应用程序中)- 我们称之为 C
当用户到达 A 或 B(无论 B 有奇怪的复杂 URL,她总是可以将它们添加为书签)时,他的请求应该包含一个授权令牌。如果没有,她就没有通过身份验证,将被重定向到 C 并提供一些登录机制 - 比如 user/pass 表单。
成功登录后,她将被重定向回 A/B(取决于她来自哪里)以完成她使用身份验证令牌所做的一切。现在,有了身份验证令牌,她就通过了身份验证。
如果她通过 A 的身份验证然后重定向到 B,则此重定向也应包含令牌,B 将知道如何信任该令牌。
现在,如果他只是打开一个新标签页,B 将看不到任何令牌,因此她将被重定向到 C,然后又被重定向回(她已经通过身份验证,还记得吗?)令牌,现在一切都很好。
我描述的是使用 OpenID 连接的常见流程,如果使用 .net,我真的建议使用 Thinktecture 的 IdentityServer 来为您完成艰苦的工作并成为您的 "C"。
另一种选择是为此类 "C" 托管为 SaaS 应用程序付费 - 查看 Auth0