跨域身份验证ASP.net MVC

时间:2022-12-04 17:54:04

I have two different web application built with ASP.net MVC. This two application may not be running in the same server nor in the same domain.

我用ASP.net MVC构建了两个不同的web应用程序。这两个应用程序可能不在同一服务器或同一域中运行。

I would like that if a user login in one of them, automatically should be login in the other. The same should work with logout.

我希望如果用户在其中之一登录,自动应该在另一个登录。同样的道理也适用于注销。

Which do you think is the best solution? Do you know about some example code?

你认为哪一个是最好的解决办法?你知道一些示例代码吗?

Thanks!

谢谢!

--- EDITED WITH MORE INFO ---

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

Use case scenario:

用例场景:

The user has the web application A opened on a tab, and at some point of the app there is a link that redirects the user to the web application B. If he is logged in on A, I would like to show him the full page, and if he is not, redirect him to the login form.

用户web应用程序打开一个选项卡,并在某种程度上的应用有一个链接将用户重定向到web应用程序b。如果他是登录,我想要给他完整的页面,如果他不是,他重定向到登录表单。

Why I need to do it:

为什么我需要这么做:

Applications A and B are already built. Apparently, the only way of accessing B is clicking on the link located in A, that only is shown if you have previously logged. The problem is that if you know the URL of some page of B (are long and complex, but still) you can write it on the browser and access B, which it means a security problem.

已经构建了应用程序A和B。显然,访问B的唯一方式是单击位于A中的链接,这只在您之前登录时显示。问题是,如果您知道B的某个页面的URL(虽然很长也很复杂),您可以在浏览器上写它并访问B,这意味着安全问题。

6 个解决方案

#1


6  

I assume you cannot communicate between applications A and B using any shared store. (This could allow some shared session implementation).

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

The more industry standard way (OpenID Connect) of doing that is like some of the other answers have hinted at. I will try and give more details to get you on the right track.

更符合行业标准的方式(OpenID连接)就像其他一些答案所暗示的那样。我会尽量提供更多的细节,让你走上正轨。

Both application A and B should relay the authentication process to a trusted 3rd party (which could be hosted in withe A, B or a different application altogether) - Let's call it C

应用程序A和B都应该将身份验证过程传递给受信任的第三方(可以托管在withe A、B或完全不同的应用程序中)——我们称之为C

When the user arrives at either A or B (no matter that B has weird complicated URLs, she can always bookmark those) his request should contain an authorization token. If it doesn't, she is not authenticated and would be redirected to C and presented with some login mechanism - say user/pass form.

当用户到达A或B时(无论B有奇怪复杂的url,她都可以将它们书签),他的请求应该包含一个授权令牌。如果没有验证,她将被重定向到C,并显示一些登录机制——比如user/pass表单。

After successful login, she is redirected back to A/B (depending on where she came from) to complete what ever she was doing with the authentication token. Now, having the authentication token present she is authenticated.

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

If she is authenticated with A and then redirected to B, this redirect should contain the token as well, B would know how to trust that token.

如果她通过A验证,然后重定向到B,那么这个重定向也应该包含令牌,B将知道如何信任该令牌。

Now, If he just opens opens up a new tab, B would not see any token, and so she would be redirected to C, only to be redirected back (she is already authenticated, remember?) to B with the token, and now all is good.

现在,如果他打开一个新选项卡,B将不会看到任何令牌,因此她将被重定向到C,然后被重定向到B(她已经验证过了,记得吗?)

What I described is a common flow using OpenID connect, and if using .net, I really suggest using IdentityServer from Thinktecture to do the hard work for you and be your "C".

我所描述的是一个使用OpenID连接的通用流,如果使用。net,我真的建议使用Thinktecture中的IdentityServer来为您做艰苦的工作,并成为您的“C”。

Another option, is to pay for such "C" hosted as a SaaS application - check out Auth0

另一种选择是,以SaaS应用程序的形式支付这种“C”,检查Auth0。

#2


8  

My Answer may not be the the best one, However you can use some tricky mechanism like

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

  1. whenever you are going on another application you need to pass one token from application A to B.
  2. 当你在进行另一个应用程序时,你需要将一个令牌从应用程序A传递给B。
  3. Validate this token on B site.
  4. 在B站点上验证这个令牌。
  5. and Authorized that user based on token. (i mean apply silent or backdoor login)
  6. 并基于令牌授权该用户。(我的意思是申请静默或后门登录)

#3


5  

You can implement OAuth in A Project. You can get more help here: http://www.openauthentication.org/about

您可以在项目中实现OAuth。您可以在这里获得更多的帮助:http://www.openauthentic.org/about

#4


5  

OWIN OAuth 2.0 Authorization Server http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server

OWIN OAuth 2.0授权服务器http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20授权服务器

#5


4  

I think what you are after is CAS (Central Authentication Service) https://en.wikipedia.org/wiki/Central_Authentication_Service

我认为您需要的是CAS(*认证服务)https://en.wikipedia.org/wiki/Central_Authentication_Service

there are numbers of CAS provider available. I would recommend you to check this out https://wiki.jasig.org/display/CAS/Home

有许多可用的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

它将为您提供大量现成的解决方案,以支持使用特定语言或基于框架编写的web服务使用CAS。这将帮助您在几个小时内实现SSO解决方案。

#6


4  

Thanks to the answer of @Kaushik Thanki I have implemented some code that fix my problem. I will post here the solution that it works for me, even if it is not the optimus.

感谢@Kaushik Thanki的回答,我实现了一些代码来解决我的问题。我将在这里发布它对我有用的解,即使它不是擎天柱。

First of all, I have implemented in A a method to make a Post request to B. Inside this method I take the id of the user and I make a hash of it with some other parameter and passwords. Then, I send to B the user id, the hash, and a boolean to choose between login and logout.

首先,我在A方法中实现了对b的Post请求。在这个方法中,我获取用户的id,并用其他参数和密码对其进行散列。然后,我将用户id、散列和boolean发送给B,以在登录和注销之间进行选择。

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

After it, I have created in B a new class to handle the login logic. I have use a HttpContext.Current.Application variable to store the status of the authentication:

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

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

Probably, the answer provided by @vijay shiyani is better and more generalistic, but from my point of view it requires a lot of time to implement it.

或许,@vijay shiyani提供的答案更好,也更具有普遍性,但在我看来,它需要大量的时间来实现。

#1


6  

I assume you cannot communicate between applications A and B using any shared store. (This could allow some shared session implementation).

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

The more industry standard way (OpenID Connect) of doing that is like some of the other answers have hinted at. I will try and give more details to get you on the right track.

更符合行业标准的方式(OpenID连接)就像其他一些答案所暗示的那样。我会尽量提供更多的细节,让你走上正轨。

Both application A and B should relay the authentication process to a trusted 3rd party (which could be hosted in withe A, B or a different application altogether) - Let's call it C

应用程序A和B都应该将身份验证过程传递给受信任的第三方(可以托管在withe A、B或完全不同的应用程序中)——我们称之为C

When the user arrives at either A or B (no matter that B has weird complicated URLs, she can always bookmark those) his request should contain an authorization token. If it doesn't, she is not authenticated and would be redirected to C and presented with some login mechanism - say user/pass form.

当用户到达A或B时(无论B有奇怪复杂的url,她都可以将它们书签),他的请求应该包含一个授权令牌。如果没有验证,她将被重定向到C,并显示一些登录机制——比如user/pass表单。

After successful login, she is redirected back to A/B (depending on where she came from) to complete what ever she was doing with the authentication token. Now, having the authentication token present she is authenticated.

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

If she is authenticated with A and then redirected to B, this redirect should contain the token as well, B would know how to trust that token.

如果她通过A验证,然后重定向到B,那么这个重定向也应该包含令牌,B将知道如何信任该令牌。

Now, If he just opens opens up a new tab, B would not see any token, and so she would be redirected to C, only to be redirected back (she is already authenticated, remember?) to B with the token, and now all is good.

现在,如果他打开一个新选项卡,B将不会看到任何令牌,因此她将被重定向到C,然后被重定向到B(她已经验证过了,记得吗?)

What I described is a common flow using OpenID connect, and if using .net, I really suggest using IdentityServer from Thinktecture to do the hard work for you and be your "C".

我所描述的是一个使用OpenID连接的通用流,如果使用。net,我真的建议使用Thinktecture中的IdentityServer来为您做艰苦的工作,并成为您的“C”。

Another option, is to pay for such "C" hosted as a SaaS application - check out Auth0

另一种选择是,以SaaS应用程序的形式支付这种“C”,检查Auth0。

#2


8  

My Answer may not be the the best one, However you can use some tricky mechanism like

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

  1. whenever you are going on another application you need to pass one token from application A to B.
  2. 当你在进行另一个应用程序时,你需要将一个令牌从应用程序A传递给B。
  3. Validate this token on B site.
  4. 在B站点上验证这个令牌。
  5. and Authorized that user based on token. (i mean apply silent or backdoor login)
  6. 并基于令牌授权该用户。(我的意思是申请静默或后门登录)

#3


5  

You can implement OAuth in A Project. You can get more help here: http://www.openauthentication.org/about

您可以在项目中实现OAuth。您可以在这里获得更多的帮助:http://www.openauthentic.org/about

#4


5  

OWIN OAuth 2.0 Authorization Server http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server

OWIN OAuth 2.0授权服务器http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20授权服务器

#5


4  

I think what you are after is CAS (Central Authentication Service) https://en.wikipedia.org/wiki/Central_Authentication_Service

我认为您需要的是CAS(*认证服务)https://en.wikipedia.org/wiki/Central_Authentication_Service

there are numbers of CAS provider available. I would recommend you to check this out https://wiki.jasig.org/display/CAS/Home

有许多可用的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

它将为您提供大量现成的解决方案,以支持使用特定语言或基于框架编写的web服务使用CAS。这将帮助您在几个小时内实现SSO解决方案。

#6


4  

Thanks to the answer of @Kaushik Thanki I have implemented some code that fix my problem. I will post here the solution that it works for me, even if it is not the optimus.

感谢@Kaushik Thanki的回答,我实现了一些代码来解决我的问题。我将在这里发布它对我有用的解,即使它不是擎天柱。

First of all, I have implemented in A a method to make a Post request to B. Inside this method I take the id of the user and I make a hash of it with some other parameter and passwords. Then, I send to B the user id, the hash, and a boolean to choose between login and logout.

首先,我在A方法中实现了对b的Post请求。在这个方法中,我获取用户的id,并用其他参数和密码对其进行散列。然后,我将用户id、散列和boolean发送给B,以在登录和注销之间进行选择。

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

After it, I have created in B a new class to handle the login logic. I have use a HttpContext.Current.Application variable to store the status of the authentication:

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

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

Probably, the answer provided by @vijay shiyani is better and more generalistic, but from my point of view it requires a lot of time to implement it.

或许,@vijay shiyani提供的答案更好,也更具有普遍性,但在我看来,它需要大量的时间来实现。