Hello, everyone. I’m Chen

Today this article introduces the Spring Cloud Gateway integration OAuth2.0 implementation of authentication and authorization, involves a little more knowledge, there is no clear can see Chen’s previous article.

The table of contents is as follows:

Microservices authentication scheme

At present, there are many kinds of micro-service certification schemes, and each enterprise is also very different, but they are generally divided into two categories, as follows:

  1. The gateway is only responsible for forwarding requests, and authentication is controlled by each microservice
  2. Authentication and authentication are unified at the gateway level, and microservices are only responsible for services

What kind of solutions do you currently use?

First, let’s talk about the first plan, which has great disadvantages as follows:

  • Code coupling is so severe that each microservice maintains a set of authentication authorities
  • Unable to achieve unified authentication, development is too difficult

The second scheme is obviously the simpler one with the following advantages:

  • With unified authentication and authorization, micro services only need to perform their respective duties and focus on their own business
  • Low code coupling facilitates subsequent extensions

Chen takes the second scheme as an example to integrate Spring Cloud Gateway+Spring Cloud Security to integrate a set of unified authentication and authentication cases.

Case of architecture

Before starting the code, let’s talk about the general authentication process, the architecture is as follows:

Roughly divided into four roles, as follows:

  • Client: Requires access to microservice resources
  • Gateway: responsible for forwarding, authentication, and authentication
  • OAuth2.0 Authorization service: Responsible for authenticating authorization and issuing tokens
  • Microservice collection: A set of services that provide resources.

The general process is as follows:

1. The client sends a request to the gateway for a token

2. The gateway receives the request and forwards it to the authorization service

3. The authorization service verifies a series of identities, such as user name and password, and issues a token to the client

4. The client requests resources with the token, and the request goes directly to the gateway layer

5. The gateway verifies the token (check, expiration time check….) , authentication (the permission carried by the current token) and the permission required to access resources are compared. If the permission overlaps, they are verified and directly forwarded to the micro-service

6, micro services for logical processing

Three new services are required for the above architecture, as follows:

The name of the function
oauth2-cloud-auth-server OAuth2.0 authentication and authorization service
oauth2-cloud-gateway Gateway service
oauth2-cloud-order-service Order Resource Service

The source directory of the case is as follows:

Establishment of authentication and authorization services

Many enterprises integrate authentication and authorization services directly into the gateway, so the coupling is too high. Chen directly extracts authentication and authorization services from the gateway.

Authentication services here is no longer detailed, the last article has been introduced very clearly: OAuth2.0 combat! Use JWT token authentication!

Create a new oAuth2-Cloud-auth-server module with the following directory:

Unlike the previous article created JwtTokenUserDetailsService this class, used to load from the database of users, as follows:

For the purposes of the demonstration, we just simulated a query from a database where two users are stored, as follows:

  • User: has the ROLE_user permission
  • Admin: has the ROLE_admin and ROLE_user permissions

For this to work, you need to specify it in the security configuration file SecurityConfig, as shown below:

Also integrated registry Nacos, detailed configuration is not posted, you can see the source code. If you are not sure about Nacos, you can see the previous article: fifty-five images that tell you how strong Nacos is for the Soul Ferryman of microservices?

The case source code has been uploaded to GitHub, concern public number: code ape technology column, reply keywords: 9529 get!

Gateway Service Setup

The Gateway uses the Spring Cloud Gateway, how to build the Gateway here is no longer detailed, there is no clear can see the previous article: Spring Cloud Gateway kill a chain of 10 ask?

Create a new oAuth2-Cloud-gateway module with the following directory:

1. Add dependencies

Several oAuth2.0-related dependencies need to be added, as follows:

2. JWT token service configuration

To use the JWT token, the configuration should be the same as the authentication service token configuration, with the following code:

3. Authentication manager customization

Create a new JwtAuthenticationManager, need to implement ReactiveAuthenticationManager this interface.

The function of authentication management is to obtain the passed token, analyze it, check it, and determine the expiration time.

The detailed code is as follows:

The logic is simple: the JWT token service parses the tokens passed by the client and validates them, for example by failing to upload three validations and throwing an exception that the token is invalid.

How are exceptions thrown handled? How can I customize the returned results?

The exception thrown here can be caught by Spring Cloud Gateway’s global exception. This article has detailed introduction. Only the key code is posted below, as follows:

4. Customize the authentication manager

After authentication by JwtAuthenticationManager is successful, the token needs to be authenticated. If the token does not have the permission to access resources, the token is not allowed to pass.

New JwtAccessManager, realize ReactiveAuthorizationManager, code is as follows:

The logic here is simple: compare the permission in the token with the permission of the current request resource URI, and pass if there is an intersection.

What does the code at ① mean?

Here is the permission set corresponding to the resource URI directly extracted from Redis, so the actual development needs to maintain the corresponding relationship between the resource URI and the permission, which will not be detailed here. To demonstrate, Chen directly added the permission of two resources to Redis when the project started, the code is as follows:

Note: The mapping between resource URIs and permissions needs to be maintained during actual development.

What does the code at ② mean?

This code is simply fetching the set of permissions in the token

What does the code at ③ mean?

This code is to compare the two permissions, there is an intersection, then release.

5. Customize the result when the token is invalid or expired

In step 4, if the token is invalid or expired, it returns directly, where you need to customize the prompt.

Create a new RequestAuthenticationEntryPoint, realize ServerAuthenticationEntryPoint, code is as follows:

6. No right to customize results within time limit

During the authentication in Step 4, if the user does not have the permission, the user will be returned directly. You also need to customize the prompt information.

Create a new RequestAccessDeniedHandler, realize ServerAccessDeniedHandler, code is as follows:

7. OAuth2.0 related configuration

After the six steps above, the components are ready and are now configured directly into OAuth2.0.

Create a new SecurityConfig configuration class annotated with @enableWebFluxSecurity, not @enableWebSecurity because the Spring Cloud Gateway is based on Flux implementation. The detailed code is as follows:

The configuration items are as follows:

  • Authentication filters, which leverage validation of tokens by the authentication manager
  • Authentication manager, token failure exception handling, unauthorized access exception handling
  • Whitelist Configuration
  • Configuring cross-domain filters

8. Global filter customization

Consider: after successful authentication at the gateway level, how does the downstream microservice obtain the detailed information of the current user?

Chen here is to parse out the user information carried by the card, package it into JSON data, and then put it into the request header through Base64 encryption, and forward it to the downstream micro service.

In this way, the downstream microservice only needs to decrypt the JSON data in the request header to retrieve the user’s details.

Therefore, we need to define a global filter in the gateway to intercept requests and parse tokens. The key code is as follows:

The code logic is as follows:

  • Check whether it is a whitelist
  • Verify that the token exists
  • Parse the user information in the token
  • Encapsulate user information into JSON data
  • Encrypt JSON data
  • The encrypted JSON data is placed in the request header

Ok, after the above 8 steps, the complete gateway is set up successfully.

The case source code has been uploaded to GitHub, concern public number: code ape technology column, reply keywords: 9529 get!

Order micro-service establishment

Because authentication is done at the gateway level (down to each URI), microservices do not need to integrate Spring Security for separate permission control.

Therefore, the microservice here is relatively simple. It only needs to decrypt the encrypted user information transmitted by the gateway layer and put it into the Request, so that the microservice can obtain the user information at any time.

Create a new oauth2-cloud-order-service module with the following directory:

Create a new AuthenticationFilter to decrypt user data passed by the gateway. The code is as follows:

Create two new interfaces and return the current login user information as follows:

Note: The permissions required by the above two interfaces have been put into Redis as follows:

  • / ORDER /login/info: both ROLE_admin and ROLE_user can be accessed
  • /order/login/admin: ROLE_admin

The case source code has been uploaded to GitHub, concern public number: code ape technology column, reply keywords: 9529 get!

Why put URIs and permissions in Redis?

The authentication manager of the gateway directly obtains the permissions corresponding to the URI from Redis and compares them with the permissions in the token. Why do you want to do this?

This method is commonly used in enterprises. Authentication is completely placed at the gateway level and dynamic permission verification is implemented. Of course, some directly control the interface’s permissions within each microservice.

Chen’s scheme requires additional maintenance of URI and permission correspondence, of course, this difficulty is very low, easy to implement.

It is only one kind of scheme, and whether to choose it or not should be considered at the architectural level.

test

Start the three services as follows:

1. Log in to user in password mode and obtain the token as follows:

2. Access /order/login/info interface with user’s token as follows:

You can see success returned because you have the ROLE_user permission.

3, use user’s token to access /order/login/admin interface as follows:

You can see that the direct return without access is blocked directly at the gateway layer.

conclusion

This article is just a simple integration of gateway +OAuth2.0, the actual development of some details to be improved, due to the length of the article, the subsequent introduction of……