Recently, our group has to integrate A management system A with another system B. In order to make it more convenient for users and avoid repeated login of multiple systems, we hope to achieve such an effect — users only need to log in once to operate in these two systems. This is clearly what ** Single sign-on ** achieves, just in time to blatantly learn a wave of Single sign-on knowledge.

The main contents of this paper are as follows:

  • SSO is introduced
  • Comparison of several implementations of SSO
  • Spring Boot single sign-on based on JWT

Note: THE concept of SSO has been around for a long time and there are very mature implementations on various platforms such as OpenSSO, OpenAM, Kerberos, CAS, etc. Of course maturity often means complexity. This article does not discuss the use of mature solutions, nor does it consider SSO in CS applications.

What is the SSO

Single point of view is: after logging in, you can access other trusted platforms without logging in. For example, after we log in to Taobao, we can open the home page of Tmall and find that it is already logged in. SSO is a popular solution for enterprise business integration.

How to implement SSO

We all know that the current HTTP protocol is stateless, that is, the first request and the second request are completely independent and unrelated, but in reality our business logic is stateful, so cookie-session mechanism is introduced to maintain the state. The browser stores a sessionId, and the background stores the data associated with the sessionId. Carry this sessionId every time you make a request to the background to maintain the state. Then there are cookies. When the browser sends a request, it automatically puts the data in the cookie into the request and sends it to the server, without manual setting.

Then we can consider what is the core of implementing SSO? The answer is how to make platform A login, other platforms can also obtain platform A’s login information (in cookie-session mechanism, sessionId).

Scheme 1: Cookie sharing

In the system based on cookie-session mechanism, after logging in to the system, a sessionId will be returned and stored in the cookie. If we can enable another system to obtain the cookie, we will get the credential information without logging in again. It just so happens that browser cookies can do the trick (see Web Cross-domain and Cookie Learning).

Cookies allow cookies to be shared between different ports of the same domain name (or parent domain name), unlike HTTP’s same-domain policy (HTTP requests are considered cross-domain if the protocol, domain name, and port are not identical). Therefore, simply deploy multiple application foreground pages to the same domain name (or parent-child domain name) and then share sessions to achieve single sign-on (SSO). The structure is as follows:

The obvious limitation of the above scenario is that not only the foreground pages need to share cookies, but also the background pages need to share sessions (JWT can be used to kill sessions, but introduces new problems, which are not explored here). The scheme is too simple to be explained further.

Scheme 2 is based on callback implementation

As can be seen from the above, to achieve single sign-on, users only need to share their identity credentials with each system, so that the background can know who is visiting now. Can achieve a login, everywhere access to the effect, it is very convenient. In the session mechanism, the sessionId is shared, and multiple backends use the same session source. Here we use a new jWT-BASED token method to implement. For those who do not know JWT, please read this article: Java-jwt generation and verification. To put it simply, JWT can carry information that cannot be tampered with (a tamper will result in verification failure), so we can directly put user ID and other non-sensitive information into JWT to eliminate the background session. Then all we need to do is share the JWT with each platform page. The system architecture is as follows:

In this architecture, there is no need for any connection between business system A and business system B, both of which only deal with the SSO authentication platform, so they can be deployed arbitrarily without any restrictions on the same domain. How do you share identity credentials (i.e., JWT strings)? This is where we’re going to use the URL parameter to do the SAO operation. The text summed it up like this: JWT is stored in the localStore(not necessarily localStore, cookie, sessionStore) at the front of the authentication platform, and then the business platform jumps to the front desk of the authentication center with its own callback address. The front desk of the authentication center takes UJWT as the URL parameter. Jump back to the callback address, completing the JWT sharing.

The text is probably indecipherable, but here’s a map of the process:

I believe you can get a general idea of how JWT is shared by the above flow chart. If you still don’t understand it, let’s continue to look at the following simple SSO authentication implemented by spring Boot. There are two main systems: SSO authentication center and system A (system A runs on different ports to be system A, B, C, and D).

In actual combat

Implement SSO authentication center

In addition to the spring Boot Web basic dependencies, only the following additional dependencies are required:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.</version>
</dependency>
<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
  <version>3.7.0</version>
</dependency>
Copy the code

For the full POM file, go to Github.

The background implementation

There’s not a lot going on in the background, but here are 5 ways to do it:

  • /login: A JWT token is issued after successful login

    In demo, the user name and password are the same. If the login succeeds, the token is returned
  • /checkJwt: Check the validity of JWT

    Check whether the passed JWT-token is valid and return a list of invalid JWTS
  • /refreshjwt: refresh JWT

    Determine if the JWT is about to expire, and if so, generate a new JWT and return
  • /inValid: disables a JWT

    How to invalidate JWT has always been a troublesome problem with both advantages and disadvantages. In this example, a random secret key is generated for each JWT, and JWT –secret is saved in Redis. If you want to inactivate a CERTAIN JWT, you only need to delete the record in Redis (so that secret cannot be obtained during decryption). But this makes the stateless authentication mechanism stateful (documenting the JWT/Secret correspondence).

To summarize, the SSO backend does two main things: validate username and password return JWT; Verify that the JWT is valid. See the code in the SSO directory on Github for details.

The front desk to implement

The logic of the front desk is complicated and not easy to understand. If you do not understand, read the above flow chart several times.

Back to the point of SSO: sharing login status. How do you share the login status (in this case, the JWT string) in the foreground? Due to browser limitations, there is no way to share data directly other than cookies. Since there is no direct sharing, there must be an indirect way!

The solution is a callback. When system A switches to SSO foreground, the SSO foreground passes the current path as the URL parameter to SSO foreground. After obtaining the JWT, SSO foreground switches to the URL path from System A and takes the JWT as the URL parameter. This completes one share of JWT, from sso share to system A.

For example: You order takeout, how will someone get it to you? Obviously you leave an address, have someone bring a meal to that address, and then you can eat. This is very familiar with JWT delivery.

System A say: I’m going to JWT, quick send it to this address on http://localhost:8081/test1/.

SSO said: ok, this is legal address can send JWT, it will jump in the past: http://localhost:8081/test1/? jwt=abcdefj.asdf.asdfasf

System A says, “Nice, nice.”

Note that there is a catch: if another malicious system C installs the same format to jump to SSO and wants to get JWT, this obviously should not be given to it. Therefore, when jumping back, we should determine whether the callback address is legitimate and whether it can be given to JWT. We can request judgment from the background or directly write the legitimate address in the SSO front desk. We don’t do that in demo.

Implementing business system

The code of the service system is very simple. It mainly uses an interceptor to intercept HTTP requests, extract tokens, and verify whether the token is valid to the SSO authentication center. Otherwise, an error is returned to the front end. Too simple to post code, go to Github to see it.

The effect

Above said a large string of principles, in fact, the difficult part is also difficult in principle, code implementation is not so complex. I will not post the code here, if necessary, go directly to Github to see.

Here are some renderings:

  • System A logs in to the system for the first time

You can see that you need to jump to sso authentication center and enter the user name and password for login authentication for the first time. The interface request succeeds after the login and jump back. Procedure

  • Change the boot port of SYSTEM A to 8082 and start again as system B

It can be seen that there is no need to log in this time. After jumping to the authentication center, it will immediately jump back. If the alert is removed, the jump process will not be visible.

Finally log out in any system, will let all systems out of the login.

After system A logs in to the system, system B and system C do not need to enter the user name or password for login. If you go fast enough you won’t even notice the process of switching to SSO and jumping back.

Source: making

This original published on: www.tapme.top/blog/detail…

Scan the official wechat account FleyX to learn notes and get more dry goods