This article brings you relevant knowledge about authentication. It mainly introduces the implementation ideas of authentication in microservices? Is there any good solution to achieve this? Let’s take a look at it together, I hope it will be helpful to everyone.
Some friends just happened to ask this question on WeChat recently, so I came to chat with you. This article mainly talks about ideas with friends without writing code. You can combine it with my previous articles and you should be able to write the code for this article yourself. Of course, the ideas are just my own practical experience and may not be the most perfect solution. Friends are welcome to discuss it in the comments.
First of all, friends know that no matter whether we study Shiro or Spring Security, no matter what functions there are, there are two cores:
Authentication
Authorization
So, we deal with authentication issues in microservices, and we can also use these two aspects to consider.
Authentication, to put it bluntly, means login. The traditional Web login is a Cookie Session solution, which relies on the local memory of the server. In microservices, due to the large number of services, this solution is obviously no longer suitable.
Some friends may say to use Redis SpringSession for session sharing. This is a way, but it is not the best solution because the performance and scalability of this solution are relatively poor.
Therefore, it is recommended to use tokens for authentication in microservices. You can choose JWT tokens, which is also a commonly used solution at present. However, friends who are familiar with JWT know that pure stateless login cannot achieve logout, which is very troublesome. Therefore, in practical applications, simply using JWT is not enough. Generally, it is necessary to combine it with Redis to convert the generated JWT characters. The string is also saved on Redis and the expiration time is set. When determining whether the user is logged in, you need to first check whether the JWT string exists on Redis. If it exists, then parse the JWT string. If it can be parsed successfully, there will be no Problem, if it cannot be parsed successfully, it means that the token is illegal.
This way of mixing stateful login and stateless login may seem a bit nondescript, but for now, this compromise is considered a feasible solution.
In fact, the above solution, to put it bluntly, is no different from the traditional Cookie Session. The ideas are almost completely copied: the traditional Session is replaced by Redis; the traditional shuttle between the server and the browser The jsessionId in between is replaced by a JWT string; the traditional jsessionId is transmitted through Cookie, and the current JWT is transmitted through the request header after being manually set by the developer; the traditional Session can be automatically renewed, but now JWT is used to renew manually, each time When the first request reaches the server, check the expiration time of the token on Redis. If it is about to expire, reset it. Everything else is exactly the same.
This is the choice of authentication scheme.
Authorization in microservices can also be done using the Shiro or Spring Security framework, which saves trouble. Considering that the microservice technology stack is a product of the Spring family, it is recommended that everyone first choose Spring Security in terms of permission framework (if any friends are not familiar with Spring Security, you can reply to ss in the background of the WeChat official account, there are tutorials) .
Of course, if you think Spring Security is more complicated and want to do it yourself, you can do it. If you do it yourself, you can also use Spring Security's ideas. One of Song Ge's recent projects is like this:
After the request reaches the microservice, first find various information about the current user, including the current user Information such as roles and permissions owned is then stored in the ThreadLocal object bound to the current thread. On the other hand, customize permission annotations and role annotations, parse these annotations in aspects, and check whether the current user has the required roles/permissions, etc.
Of course, if you use Spring Security, you don’t need custom annotations for the above. You can just use the ones that come with Spring Security. You can also experience more richness in Spring Security. safety features.
So where are the authentication and authorization done?
Let’s talk about authentication first. Authentication can be simply divided into two steps:
Login
Verification
Generally speaking, we can do a separate authentication service for login. When the login request reaches the gateway, we forward it to the authentication service to complete the authentication operation.
In the authentication service, we check whether the user name/password is OK and whether the user status is OK. If there is no problem, generate a JWT string, and at the same time store the data into Redis, and then JWT string returned.
If the system has a registration function, the registration function is also completed on this microservice.
Verification refers to verifying whether the user has logged in when each request arrives.
Of course this can be done together with 2.1, but Brother Song does not recommend it. The problem is that if it is a request to create an order, this request is originally forwarded to the order service through the gateway. However, at this time, the service in Section 2.1 must be called on the gateway for login verification. If there is no problem, it will be forwarded to In terms of order service, this is obviously very time-consuming and unreasonable.
A better way is to directly verify whether the requested token is legal on the gateway. This verification itself is relatively easy. To verify whether the token is legal, we only need to check whether the token exists on Redis. As long as the JWT token can be successfully parsed, this operation can be done on the gateway.
Taking the Gateway as an example, we can customize the global filter and verify the token of each request in the global filter. If the verification passes, the request will be forwarded, otherwise it will not be forwarded.
After passing the verification and forwarding to the specific microservice, we can put the parsed user id and user name and other information into the request header, and then forward it to reach each specific microservice. After that, you will know who sent the request and what roles/permissions this person has, so that you can do the next step of permission verification.
What Song Ge did is to define a public module. All microservices depend on this public module. An interceptor is defined in this public module, which will intercept every request. From the request header Get the user ID from Redis, and then get the specific user information from Redis and store it in ThreadLocal. In subsequent method calls, if you need to determine whether the user has a certain permission, you can obtain it through ThreadLocal.
This is roughly the process.
Authorization cannot be done on the gateway, it still has to be done on each microservice.
We can roughly divide authorization on microservices into two categories:
Requests sent from the front end (external requests).
Requests sent from other microservices (internal requests).
For external requests, just treat them according to normal permission verification, custom annotations or using frameworks such as Spring Security. Yes, if it is a custom annotation, you can combine it with AOP to define aspects to handle permission annotations by yourself. Of course, these functions are basically needed by every microservice, so they can be extracted into a public module. Just depend on it in different microservices.
For internal requests, authentication is not normally required and internal requests can be processed directly. The problem is that if OpenFeign is used, the data is exposed through the interface. If there is no authentication, there will be worries about external requests calling this interface. For this problem, we can also customize the annotation AOP, and then request the call internally. When , add an additional header field to distinguish it.
Of course, when an internal request reaches a microservice, it also needs to be authenticated, just like when the request is forwarded from the gateway to each specific microservice, authentication is required, but obviously, we don’t need to use it every time When OpenFeign calls other services, it passes a bunch of authentication information. We can define an OpenFeign request interceptor by implementing the feign.RequestInterceptor
interface. In the interceptor, the request is uniformly set for OpenFeign requests. header information.
Okay, regarding authentication in microservices, this is how we currently do it. Friends are welcome to leave a message and discuss it together.
Recommended learning: "小program video tutorial" "Java video tutorial"
The above is the detailed content of An article explaining in detail how to implement microservice authentication. For more information, please follow other related articles on the PHP Chinese website!