Small Hub read:
Explain video also synchronous release, remember to see ha, one button three link wow.
Video tutorial: www.bilibili.com/video/bv1SD…
This system, must learn the user – service authentication, service – service authentication that set, this is to learn.
Introduction to the
Cloud-platform is the first micro-service development Platform based on Spring Cloud in China. It has a unified authorization and authentication background management system, including multiple modules such as user management, resource rights management and gateway API management. It supports the parallel development of multi-service systems and can serve as the development scaffolding for back-end services. Simple code, clear architecture, suitable for learning and direct project use. The core technology adopts Spring Boot 2.1.2 and Spring Cloud (Greenwich.RELEASE) related core components, Nacos registration and configuration center, integrated flow guard Sentinel, and vue-element-Admin component at the front end. Elastic Search integrates itself.
Video explanation of station B:
Ps: Note that this article is based on cloud-Platform V2.5, not the latest version!
Technology selection
Front end: vue – element – admin
Backend: SpringCloud (Eureka, Gateway, Admin, Sidecar, Hystrix, Feign, Ribbon, Zipkin), TK + Mybatis, Lucene, JWT, rest
The project structure
Ace ws-security ace - modules -- -- -- -- -- -- -- -- -- -- -- -- -- -- the public service module based system, search, (OSS) ace - auth -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- service authentication center Ace - gate -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ace - common gateway load center -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- general scaffolding ace - control -- -- -- -- -- -- -- -- -- -- -- -- -- -- operations center (monitoring, link) Ace-sidebar -------------- Invokes third-party language servicesCopy the code
Project start
Note: Cloud-platform is a project separated from the front and back ends. Therefore, the back-end services must be started first. After the back-end services are started, the front-end projects can be started.
The environment
- Mysql, Redis, Maven
- jdk1.8
- IDE plug-in, lombok plug-in, specific Baidu can be
- node
The front end
Git link: gitee.com/geek_qi/clo…
- Clone to the local computer and go to cloud-platform-UI to open the command-line window (CMD).
- Because node.js is involved, you need to install NPM, Node, etc
Node.js installation tutorial: nodejs.cn/download/ download the MSI version and install it.
If the cli is displayed, the installation is successful.
Package dependencies for the project
# 1, installation taobao mirror rely on NPM install - g CNPM - registry=https://registry.npm.taobao.org # 2, install project depend on CNPM NPM install # start service run devCopy the code
After successful startup, the link http://localhost:9527/ will be automatically opened
The back-end
First clone project down (v2.5) : gitee.com/geek_qi/clo…
SQL > select * from db;
Alter database account password (CTRL + SHIRT + R, search datasource:)
Next, start Redis, and then start our services in installation sequence
CenterBootstrap -> AuthBootstrap -> AdminBootstrap -> GatewayServerBootstrapCopy the code
Other monitoring or services may not be started.
Service description
ace-auth-server
Key categories:
-
AuthController
- For controllers that start with/JWT, log in, refresh, and verify JWT
- The gateway does not block the request for this link
-
ClientController
- You can obtain the resources related to authorization based on the ID and key of the exposed interface
-
ServiceController
- Background management system service management module interface
-
ClientTokenInterceptor
- Intercepts feIGN interface requests and automatically adds request header tokens
-
ServiceAuthRestInterceptor
- The intercepted URL is /service/** (WebConfiguration)
- Invocation authentication between services
- It is called in feign or restTemplate mode
-
UserAuthRestInterceptor
- The intercepted URL is /service/** (WebConfiguration)
- Get user’s token and parse, add user information to session context (ThreadLocal)
-
OkHttpTokenInterceptor
- Intercept all feign requests and OkHttp rewrite requests
- OkHttp3 is a powerful mechanism to monitor, rewrite, and retry calls
Module analysis
The user authorization
First of all, let’s make clear the login process, what happened during and after login, so we open the front login page, press F12, and then click Login, you can see the following actions:
- Click login, and submit the form: http://localhost:9527/api/auth/jwt/token
# the return value {"status":200,"data":"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInVzZXJJZCI6IjEiLCJuYW1lIjoiTXIuQUciLCJleHAiOjE1NjE0NDEyN TZ9.tXNw8nhAFmI4QIQDpKy4DzWtJSTpfwD4685JqbA2pGScdyfXt_5DDs_r1gVZA4CwQC4oZxBsmLKZGclTLGc4HKeXlP2PiVoHZfSWymFRLNfvFqOzKUET J6WpyDqK55yjf1wddTBD3VzSFvY49uunvozEcb2oFjOs3M_I2sgxAAU","rel":false}Copy the code
After successful login, a JWT token value is returned, which should be the token used to identify the user’s identity.
- Ajax requests for user information and the menu list: http://localhost:9527/api/admin/user/front/info? token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInVzZXJJZCI6IjEiLCJuYW1lIjoiTXIuQUciLCJleHAiOjE1NjE0NDEyNTZ9.tXNw8nhAFmI4 QIQDpKy4DzWtJSTpfwD4685JqbA2pGScdyfXt_5DDs_r1gVZA4CwQC4oZxBsmLKZGclTLGc4HKeXlP2PiVoHZfSWymFRLNfvFqOzKUETJ6WpyDqK55yjf1wd dTBD3VzSFvY49uunvozEcb2oFjOs3M_I2sgxAAU
# the return value {"id":"1","username":"admin","name":"Mr.AG","description":"","menus":[{"code":"userManager","type":"menu","uri":"/admin/ User ", "method" : "GET", "name" : "access", "menu" : "user management"}, {" code ":" baseManager ", "type" : "menu", "uri" : "/ admin", "method" : "GET", "name" :" Access ","menu":" basic configuration management "}, ... (the deleted part), {" code ":" serviceManager: btn_clientManager ", "type" : "button", "uri" : "/ auth/service / {*} / client", "method" : "POS T","name":" service authorization ","menu":" service management "}]}Copy the code
Also notice the information in the request header: it contains the JWT token that was logged in earlier, and the name is Authorization. All subsequent requests will carry this Authorization to identify the user.
Let’s go through the process:
-
The client click on the button to launch the login request at http://localhost:9527/api/auth/jwt/token
- The gateway gate is first reached through our AccessGatewayFilter
- Gets the request URI, method
- Check whether the address is not intercepted
- Gate: ignore: startWith: /auth/ JWT
- So the gateway filter proxies requests directly to the ACE-Auth service
- The gateway gate is first reached through our AccessGatewayFilter
-
Gateway Ace-gateway-v2 proxy and filtering configuration
Rule # gateway proxy spring: cloud: gateway: a locator: enabled: true routes: # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = - id: ace-auth uri: lb://ace-auth order: 8000 predicates: - Path=/api/auth/** filters: - StripPrefix=2 - id: ace-admin uri: lb://ace-admin order: 8001 predicates: - Path=/api/admin/** filters: - StripPrefix=2 gate: ignore: startWith: /auth/jwtCopy the code
So let’s go into ace-Auth and find the corresponding controller, which we can find here:
@RestController
@RequestMapping("jwt")
@Slf4j
public class AuthController { @RequestMapping(value = "token", method = RequestMethod.POST)
public ObjectRestResponse<String> createAuthenticationToken(
@RequestBody JwtAuthenticationRequest authenticationRequest) throws Exception {
log.info(authenticationRequest.getUsername()+" require logging...");
final String token = authService.login(authenticationRequest);
return new ObjectRestResponse<>().data(token);
}
}
Copy the code
The only method in this method is authService.login, and when I click on this method, I find another method in this method called UserService. validate, which is an feign interface
@FeignClient(value = "ace-admin",configuration = FeignConfiguration.class)
public interface IUserService { @RequestMapping(value = "/api/user/validate", method = RequestMethod.POST)
public UserInfo validate(@RequestBody JwtAuthenticationRequest authenticationRequest);
Copy the code
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
Inter-service authentication
The class above, userService.validate, has this annotation
@feignClient (value = "ace-admin",configuration = feignConfiguration. class) indicates that the ace-admin service is invoked declaratively. We can see that there is a configuration = feignConfiguration. class, We open FeignConfiguration @Configuration Public class FeignConfiguration {@bean ClientTokenInterceptor getClientTokenInterceptor(){ return new ClientTokenInterceptor(); }}Copy the code
Open ClientTokenInterceptor again:
public class ClientTokenInterceptor implements RequestInterceptor { private Logger logger = LoggerFactory.getLogger(ClientTokenInterceptor.class); @Autowired private ClientConfiguration clientConfiguration; @Autowired private AuthClientService authClientService; @override public void apply(RequestTemplate RequestTemplate) {logger.info("----> add token header for feign call "); try { requestTemplate.header(clientConfiguration.getClientTokenHeader(), authClientService.apply(clientConfiguration.getClientId(), clientConfiguration.getClientSecret())); } catch (Exception e) { e.printStackTrace(); RequestInterceptor is an interceptor that adds a request header to a feIGN request when it makes a remote call. Therefore, the request header has the identity token of the current service, and the receiving server can identify the source server based on the token.Copy the code
Now let’s see how the receiver can tell. ServiceAuthRestInterceptor
public class ServiceAuthRestInterceptor extends HandlerInterceptorAdapter { private Logger logger = LoggerFactory.getLogger(ServiceAuthRestInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object Handler) throws Exception {logger.info("------> Check whether service A has permission to access service B ~"); HandlerMethod handlerMethod = (HandlerMethod) handler; / / configure the annotations, not for service intercept IgnoreClientToken annotation = handlerMethod. GetBeanType (). The getAnnotation (IgnoreClientToken. Class); if (annotation == null) { annotation = handlerMethod.getMethodAnnotation(IgnoreClientToken.class); } if(annotation! =null) { return super.preHandle(request, response, handler); } String token = request.getHeader(serviceAuthConfig.getTokenHeader()); IJWTInfo infoFromToken = serviceAuthUtil.getInfoFromToken(token); String uniqueName = infoFromToken.getUniqueName(); For (String client: serviceAuthUtil getAllowedClient ()) {/ / ace - auth, ace - gate the if (client) equals (uniqueName)) {return super.preHandle(request, response, handler); } } throw new ClientForbiddenException("Client is Forbidden!" ); }}Copy the code
Look at the code first to see if there are any IgnoreClientToken annotations, and skip them if there are. If not continue to get calls token of backend server, and then to obtain the current server allows access to lient (serviceAuthUtil. GetAllowedClient ()), and call the matching name is within the allowed the client, if allowed to continue, Forbidden. So it’s pretty clear. So where is this relationship between clients and clients that are allowed to access maintained, there are actually two tables
- Auth_client: indicates the ID and name of the client
- Auth_client_service: client association table that the server is allowed to call
From this table, we can figure out what is allowed and what is not
Cloud-platform Authentication logic. PNG
Optimization of inter-service invocation. PNG
conclusion
The first thing to do
- Create all needed modules and basically build the framework
- Add, delete, change and check the packaging, interface specifications
- Global exception capture encapsulation
- Unit testing
- General utility class
The second thing
- Determine the authorization mode of the service (JWT, OAUTH2, etc.)
The third thing
- Service internal authentication
- Access control
(after)
Video tutorial: www.bilibili.com/video/bv1SD…