Official account: Java Xiaokaxiu, website: Javaxks.com

Author: Zhang Yongheng, link: urlify.cn/RVvaim

preface

In B/S systems, the login function is usually implemented based on cookies. When a user logs in successfully, the login status is usually recorded in the Session or a Token is issued to the user. Either way, some information (Session ID or Token) needs to be stored in the client and the client is required to carry it in each subsequent request. In such a scenario, it is undoubtedly the most convenient to use cookies. Therefore, we generally store the Session ID or Token in cookies. When the server receives the request, it verifies the information in cookies to determine whether the user logs in.

Single sign-on (SSO) allows a user to log in to multiple applications On the same account platform once to access all trusted applications. For example, Baidu Tieba and Baidu Map are two different application systems of Baidu Inc. If a user logs in to Baidu Tieba and does not need to log in to Baidu Map again, it means that the single sign-on between Baidu Tieba and Baidu Map is realized.

The essence of single sign-on is to share login state across multiple applications. If the user’s login status is recorded in the Session, to realize the shared login status, the Session must be shared first. For example, the Session can be serialized into Redis, so that multiple application systems can share the same Redis and directly read the Redis to obtain the Session. Of course, this is not enough, because different application systems have different domain names. Although sessions are shared, Session IDS are often stored in browser cookies, so there are scope limitations and cannot be transferred across domain names. That is to say, after users log in app1.com, The Session ID is carried automatically in the request header only when the browser accesses App1.com, and is not carried when the browser accesses App2.com. The key to single sign-on is how to share Session ids (or tokens) across multiple domains.

Implementation method 1: parent domain Cookie

Let’s talk about the scope of cookies before we implement them.

The Cookie’s scope is determined by both the domain and path attributes. The valid value of domain attribute is the domain name/IP address of the current domain or its parent domain. In Tomcat, domain attribute is the domain name/IP address of the current domain by default. The valid value of the path attribute is a path starting with a slash (/). In Tomcat, the path attribute defaults to the context path of the current Web application.

If the domain property of the Cookie is set to the parent domain of the current domain, it is considered a parent domain Cookie. Cookies have a feature that the cookies in the parent domain are shared by the quilt domain. In other words, the cookies in the child domain automatically inherit from the parent domain.

Taking advantage of this feature of cookies, it is not difficult to imagine that the Session ID (or Token) can be stored in the parent domain. Yes, we only need to set the domain property of the Cookie to the domain name of the parent domain (master domain), and set the path property of the Cookie to the root path, so that all subdomain applications can access the Cookie. However, this requires the domain name of the application system to be established under a common main domain name, such as Tieba.baidu.com and map.baidu.com, which are both established under the main domain name baidu.com, so they can realize single sign-on (SSO) in this way.

Summary: This implementation is relatively simple, but does not support cross-master domain names.

Implementation mode two: Certification center

We can deploy a certification authority, which is a separate Web service that handles login requests.

Users log in to the authentication center in a unified manner. After successful login, the authentication center records the login status of the user and writes the Token into the Cookie. (Note that this Cookie belongs to the authentication authority and is not accessible to the application system.)

The application system checks whether the current request has a Token. If the request does not have a Token, the user has not logged in to the current system and is redirected to the authentication center. Because this operation automatically brings the authentication authority’s Cookie, the authentication authority can know whether the user has logged in based on the Cookie. If the authentication center finds that the user has not logged in, the authentication center returns to the login page and waits for the user to log in. If the user has logged in, the authentication center does not allow the user to log in again. Instead, the authentication center switches back to the target URL and generates a Token after the target URL and sends the Token back to the target application system.

After obtaining the Token, the application system needs to verify the validity of the Token with the authentication center to prevent users from forging the Token. After confirming the information, the application system records the login status of the user, writes the Token into a Cookie, and permits the access. (Note that this Cookie belongs to the current application and is not accessible to other applications.) When the user accesses the current application system again, the Token is automatically worn. The application system verifies the Token and discovers that the user is logged in. Then there is no problem with the authentication authority.

Here are two open source implementations of certification authorities:

  • Apereo CAS is an enterprise-level single sign-on system. CAS stands for Central Authentication Service. Originally a project of the Yale University Laboratory, it was transferred to the JASIG organization, which changed its name to JASIG CAS. The organization later merged with the Apereo Foundation, which changed its name to Apereo CAS.
  • Xxl-sso is a simple single sign-on system developed by Xu Xueli, engineer of Dianping. The code is relatively simple and there is no security control, so it is not recommended to be directly applied in the project. It is listed here for reference only.

Conclusion: This implementation method is relatively complex, supports cross-domain, and has good scalability. It is the standard practice of single sign-on.

Implementation method 3: Cross-domain LocalStorage

Earlier, we said that the key to single sign-on is how to share Session ids (or tokens) across multiple domains.

Parent domain cookies are a good solution, but they don’t support cross-domain. So are there any weird tricks you can use to make cookies cross domains?

Unfortunately, browsers are becoming increasingly restrictive on cookies across domains. Chrome also adds a SameSite attribute to cookies, which prohibits Cookie delivery across almost all domain requests (except hyperlinks), and only when using HTTPs, You may be allowed to accept cookies from the server in AJAX cross-domain requests.

However, in the case of the separation of the front end and the back end, there is no need to use cookies at all. We can choose to save the Session ID (or Token) to the LocalStorage of the browser, so that the front end can send a request to the back end every time, Actively pass LocalStorage data to the server. All of this is controlled by the front end, and all the back end needs to do is pass the Session ID (or Token) in the response body to the front end after the user logs in successfully.

In such scenarios, single sign-on can be implemented at the front end. After receiving the Session ID (or Token), the front-end can write it to localstorages in other domains by special means in addition to its own LocalStorage.

The key codes are as follows:

Var token = result.data.token; Var iframe = document.createElement("iframe"); iframe.src = "http://app1.com/localstorage.html"; document.body.append(iframe); / / using postMessage () method will be token is passed to the iframe setTimeout (function () {iframe. ContentWindow. PostMessage (token, "http://app1.com");  }, 4000); setTimeout(function () { iframe.remove(); }, 6000); // Bind an event listener to the HTML loaded by this iframe. When the event is triggered, LocalStorage window.addeventListener ('message', function (event) {localstorage.setitem ('token', event.data) }, false);Copy the code

The front-end uses iframe+postMessage() to write the same Token to LocalStorage in multiple domains. Each time before sending a request to the back-end, the front-end will actively read the Token from LocalStorage and carry it in the request. This enables the same Token to be shared by multiple domains.

Summary: This implementation is completely controlled by the front end, requires little back end involvement, and also supports cross-domain.

Added: Domain name classification

From a professional point of view (according to the definition in Computer Network),.com and.cn are the first level domain names (also known as top-level domain names),.com and baidu.com are the second level domain names, sina.com.cn and tieba.baidu.com are the third level domain names, and so on. A level N domain name is a direct subdomain name of a level N-1 domain name.

From the user’s point of view, the main domain name that can support independent filing is generally called level-1 domain name, such as Baidu.com and sina.com.cn. The direct sub-domain name established under the main domain name is called level-2 domain name, such as tieba.baidu.com is the level-2 domain name.

To avoid confusion, I will use the term “master domain name” instead of “level 1 domain name”.

(after)