With the development of corporate business, more and more subsystems are needed to implement SSO SSO.
In some subsystems, Redis is used to store sessions, which is originally used to solve the problem of Session sharing in application cluster deployment, but also provides support for Session sharing between applications. However, single sign-on cannot be realized by sharing sessions between applications alone.
In a single application, when a user logs in to the system, the user’s login status is stored in the Session of the server, and the SessionId is transmitted to the browser for storage through the Cookie field of the response header. When the server requests the user, the browser will automatically add cookies to the request header, so that the user’s login status can be maintained.
Using Redis to share sessions, sessions can be shared between clusters in the same way that the login state remains after the service is restarted.
After the application restarts, the browser still sends requests with cookies. If the Session has not expired, the Session obtained from Redis will continue to be used.
Therefore, although sessions can be shared between applications through Redis, the browser is required to request that each application carry the same Cookie to achieve single sign-on.
However, the browser does not support Cookie sharing between different domain names, and the server cannot control the client browser to visit sites under different domain names with the same SessionId. We have to take a different approach to single sign-on.
Although browsers do not support Cookie sharing between different domain names, applications with different subdomain names of the same master domain name can share cookies by setting the Cookie as the master domain name, on the premise that all subsystems share the same master domain name. It is desirable and undesirable, in the short term and not in the long term.
If a user clicks the button in application A to switch to application B, it can also be realized as follows: When a user clicks the button in application A to switch to application B, the SessionId is added to the link, and application B reads user information according to the SessionId and writes it to the Session.
Leaving security aside, the disadvantages of this approach are also obvious. Users cannot directly enter the domain name of application B in the browser to jump to application B, but can only jump to Application B through application A, and to return to Application A, they can only click the button from application B to jump to Application A.
It’s not a good idea to jump from app to app by clicking a button, but at least it’s a good idea to share login status with a SessionId on the jump link.
With this in mind, can we make the browser automatically add a SessionId without clicking a button?
Yes, but via redirection.
When A logged in user system, directly on the browser to modify the domain name to access the system B and system B check to the user is not login redirect requests to the system, A system is A check to the request from the system B redirected to come over, and the user has logged in, so can the SessionId joining together to redirect link, then redirects back to the system B, System B obtains the SessionId of system A, queries user information from Redis based on the SessionId, and writes the user information into the Session of system B. In this way, system B can automatically jump with the SessionId.
However, this approach requires that each system implement this functionality once, and that each system also provide login functionality.
In order to simplify the implementation, and the subsequent new system will not implement the login function repeatedly, we should consider separating the login function into an independent application. In the future, menu authorization and other functions can be migrated to this system, and other systems will not provide the login function.
After separating the login function from an independent application, the SSO SSO process is summarized as follows:
SSO is separated into an independent application with an independent domain name that provides a login page. Other applications must use SSO to log in to the application without the login page.
When receiving the request, other applications first determine whether they have logged in according to the session. If they do not log in, they are redirected to the SSO login page and the application that redirects to the SSO login page. When the user successfully logs in to the SSO, the user is redirected to the original application.
When the browser redirects to the SSO login page, the browser stores the SSO cookie. After the SSO login succeeds, SSO stores the login status of the user. SSO generates a token, redirects back to the original application, and adds the token to the redirected link.
After the SSO authentication succeeds, the user information is returned. The original application stores the user information in the Session and redirects the user information to the home page after the authentication succeeds.
If a user accesses application B by entering the domain name of application B in the browser, application B checks that the Session does not contain user information (the user is not logged in) and is redirected to the SSO application.
After the user has logged in to SSO, the browser carries a cookie when redirecting requests to the SSO application. Therefore, the SSO application detects that the user has logged in, generates a token and redirects the request back to application B.
Application B receives the redirection request, obtains the token from the request, accesses the SSO application to verify the token and obtain the user information. After obtaining the user information, application B writes the user information to the Session, and finally redirects the user to the home page.
According to the combing process, summarize the functions that each application needs to realize:
SSO applications:
- Provide login function, support redirection from where to redirection to where;
- Provide validation
token
Interface that responds to user information after successful authentication (can only respond to user’sid
, other applications query user details).
Other applications:
- If you have not logged in, jump to
SSO
, with verification of the redirection call after successful logintoken
The links; - Provided by the
SSO
Validation of the redirect calltoken
When the verification is successful, the user information is writtenSession
Redirect to the front page.
It should be noted that, assuming that the session expiration time set for SSO is one hour, if the user jumps back to application A after SSO login and then jumps to application B after no operation for one hour, the SSO session has expired and the login status cannot be synchronized, and the user has to log in again. Therefore, the SSO session expiration time should be set as required and not too short.
Implementing this process on a system where the front and back ends are separated is not easy, and there are more steps than described in this article. We encapsulated the tedious steps as much as possible by wrapping the SDK so that other applications could only rely on a JAR package for SSO and add a small amount of configuration.
The SDK blocks all requests through filters provided by servlets:
-
1. If the request is /checketSsoToken, the SSO login is successful (browser redirection) and the request carries the token parameter. In this case, the SDK needs to complete the token verification interface of SSO request, write the obtained user information into the Session, and then redirect it to the front page of the current application.
-
2. If /checketSsoToken is not displayed, check the configuration and determine whether the current request can be approved without login. If yes, the request can be approved.
Due to the separation of the front and back ends, the front end requests the interface through Ajax, and the back end judges that the response redirection without login cannot be truly redirected. Therefore, the front end is required to intercept the response of all requests. If the response header has a redirection flag, it should obtain the redirection link from the request header, and then let the browser redirect.
- 3. If the user logs out of the application, clear the user login information cached by the application before redirecting it to
SSO
Log out.
The actual connection process is as follows:
-
1. The user enters the domain name of application A in the browser and goes to the index.html page. (Nginx reverse proxy configuration implementation)
-
2. The front end invokes a back-end interface on the home page, such as obtaining a menu and triggering verification login (implemented by the front end). If the front end does not log in, it splices the redirection link and responds to the front end, requiring redirection to SSO login page (implemented by SDK encapsulation);
-
3. After the SSO login succeeds, SSO redirection invokes the URL of application A’s token verification. This URL is concatenated behind the URL as A parameter when application A redirects to SSO login. The url is provided by the backend, and the front-end is only responsible for redirection. (SSO application implementation)
-
4. Application A requests SSO’s verification token interface, writes the user information in the session, and redirects it back to the front page. (SDK package implementation)
One final thought: How do YOU synchronize your logout status?
When A user logs out in application A, only Application A and SSO know that the user logs out, but other applications do not.
It’s not that we can’t achieve it, but we’re looking for the best way. The easiest way to do this is to set Session expiration times for all applications other than SSO to be as short as possible, preferring multiple orientations.
Finally, because each application uses Shiro to implement interface permission verification and Shiro’s annotations, we adapt Shiro’s annotations in SDK for the implementation of permission verification, but completely discard Shiro.