Spring security oauth2.0 authentication and authorization 4: distributed system authentication and authorization

itread01 2021-01-14 15:49:39
spring security oauth2.0 oauth authentication


Spring Security OAuth2.0 Authentication and authorization series > [Spring Security OAuth2.0 Authentication and authorization 1 : Framework building and certification testing ](https://blog.kdyzm.cn/post/24) > [Spring Security OAuth2.0 Authentication and authorization 2 : Build resource services ](https://blog.kdyzm.cn/post/25) > [Spring Security OAuth2.0 Authentication authorization 3 : Use JWT token ](https://blog.kdyzm.cn/post/26) The previous articles explained how to build authentication services and resource services from scratch , From issuing ordinary token to issuing jwt token , Finally it's done jwt Token issuance and verification . This article will explain how to authenticate and authorize in a distributed environment .## One 、 Design ideas ![ Decentralized authorization graph .png](https://img2020.cnblogs.com/news/516671/202101/516671-20210114093941879-2038643737.png;%20charset=UTF-8) In general , A typical distributed system architecture is shown in the figure above , Here's a simple design , To complete the authentication and authorization under the distributed system . The overall design idea is to use OAuth2.0 Issue token , Use JWT Sign the token and issue JWT Token to client . Now that we have decided to use JWT The token , You don't need to call the authentication server to verify the token , Because JWT It contains all the information you need , And as long as the verification is successful , The token can be regarded as trusted and valid . As mentioned above , It can be designed like this :1. After the user requests to log in, the authentication service issues the token to the user , The browser stores the token .2. The browser carries a token when it requests resources , The gateway intercepts the request to verify the token , The method of verification is simple , Instead of requesting authentication service, use the key directly ( Symmetrical or asymmetrical ) Verification of signature , As long as the verification is successful, then jwt payload The information in is parsed into plaintext and put in the request header to forward the request to the resource service .3. Resource services get clear text information , Verify that you have permission to access the resource according to the permission information in the plaintext , If permission is granted, resource information will be returned , Without permission, return 401. To sum up , The whole idea is gateway certification , Resource Service Authentication . There will be a registry in a typical microservice architecture 、 Gateways and other services , Next, we will introduce and build related services in turn .## Two 、 The registry is built to facilitate local debugging , Here we use eureka server As a service registry , It's very easy to use ### 1. newly added maven Rely on ``` xml org.springframework.cloud spring-cloud-starter-netflix-eureka-server org.springframework.boot spring-boot-starter-actuator ```### 2. Create a new startup class ``` java@SpringBootApplication@EnableEurekaServerpublic class RegisterServer { public static void main(String[] args) { SpringApplication.run(RegisterServer.class,args); }}```### 3. New profile ``` yamlspring: application: name: register-serverserver: port: 8765 # Start port eureka: server: enable-self-preservation: false # Turn off server self protection , Client heartbeat detection 15 Within minutes the error reached 80% Service will protect , Leading others to think it's a good service eviction-interval-timer-in-ms: 10000 # Clean up intervals ( Unit millisecond , The default is 60*1000)5 Second, delete the service rejected by the client in the service registration list # shouldUseReadOnlyResponseCache: true #eureka yes CAP The theory is based on AP Strategy , To ensure strong consistency, turn off this switch CP Default does not close false Shut down client: register-with-eureka: false #false: Do not register as a client in the registry fetch-registry: false # For true When , It can start , But it's abnormal :Cannot execute request on any known server instance-info-replication-interval-seconds: 10 serviceUrl: defaultZone: http://localhost:${server.port}/eureka/ instance: hostname: ${spring.cloud.client.ip-address} prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}``` Then start the startup class , Visit the browser ,[http://127.0.0.1:8765](http://127.0.0.1:8765), The following page appears to indicate success ![eureka server.png](https://img2020.cnblogs.com/blog/516671/202101/516671-20210114093944072-1906516697.png;%20charset=UTF-8)## Two 、 The gateway is built here spring cloud gateway As a gateway ( No zuul)### 1. newly added maven Rely on ``` xml org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.cloud spring-cloud-starter-gateway 2.2.5.RELEASE org.springframework.boot spring-boot-starter-actuator org.projectlombok lombok org.springframework.security spring-security-jwt ```### 2. Create a new startup class ``` java@SpringBootApplicationpublic class GatewayServer { public static void main(String[] args) { SpringApplication.run(GatewayServer.class, args); }}```### 3. New profile ``` yamlserver: port: 8761spring: cloud: gateway: routes: - id: resource_server uri: "lb://resource-server" predicates: - Path=/r** application: name: gateway-servereureka: client: service-url: defaultZone: http://127.0.0.1:8765/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ip‐address}:${spring.application.instance_id:${server.port}}``` such , A gateway is already built , But it doesn't have the authentication function we want .### 4. newly added token The knowledge points of global filter are as follows :- Global filter to achieve GlobalFilter Interface - In order to achieve token The filter is called first , To achieve Order Interface and maximize the priority - Use JwtHelper Tool class to jwt Verification of signature , Signed key Must be configured with the certification authority key bring into correspondence with - After the successful verification, the jwt in payload Put plaintext information in token-info Of header Value to the target service. The implementation code is as follows :```java@Component@Slf4jpublic class TokenFilter implements GlobalFilter, Ordered { private static final String BEAR_HEADER = "Bearer "; /** * The value should be equal to auth-server The signatures configured in are the same * * com.kdyzm.spring.security.auth.center.config.TokenConfig#SIGNING_KEY */ private static final String SIGNING_KEY = "auth123"; @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION); // If not token, Then go straight back to 401 if(StringUtils.isEmpty(token)){ return unAuthorized(exchange); } // Verify and obtain PayLoad String payLoad; try { Jwt jwt = JwtHelper.decodeAndVerify(token.replace(BEAR_HEADER,""), new MacSigner(SIGNING_KEY)); payLoad = jwt.getClaims(); } catch (Exception e) { log.error(" Signature verification failed ",e); return unAuthorized(exchange); } // Will PayLoad Put the information in header ServerHttpRequest.Builder builder = exchange.getRequest().mutate(); builder.header("token-info", payLoad).build(); // Continue execution return chain.filter(exchange.mutate().request(builder.build()).build()); } private Mono unAuthorized(ServerWebExchange exchange){ exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } /** * Set the priority of the filter to the highest , Because as long as the certification doesn't pass , You can't do anything * * @return */ @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; }}```## 3、 ... and 、 The original resource service has been integrated OAuth2.0、Spring Security、JWT Etc , According to the current design , Need to delete OAuth2.0 and JWT Components , Leave only Spring Security Components .### 1. remove OAuth2.0、JWT Components are deleted here maven Rely on , At the same time, delete the relevant configuration ** First step , Delete maven Rely on **, Just remove the following two dependencies ``` xml org.springframework.cloud spring-cloud-starter-oauth2 org.springframework.security spring-security-jwt ```** The second step , Delete related configuration ** Will ResouceServerConfig、TokenConfig Two classes are deleted directly that will do .### 2. Add a new filter here, you need to use a filter to do , First write a filter , Realize OncePerRequestFilter Interface , The function of the filter is to get the information from the gateway token-info Plain text , Package it as JwtTokenInfo thing , And add this information to SpringSecurity Context for later authentication . The code is implemented as follows :``` java@Component@Slf4jpublic class AuthFilterCustom extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ObjectMapper objectMapper = new ObjectMapper(); String tokenInfo=request.getHeader("token-info"); if(StringUtils.isEmpty(tokenInfo)){ log.info(" Not found token Information "); filterChain.doFilter(request,response); return; } JwtTokenInfo jwtTokenInfo = objectMapper.readValue(tokenInfo, JwtTokenInfo.class); log.info("tokenInfo={}",objectMapper.writeValueAsString(jwtTokenInfo)); List authorities1 = jwtTokenInfo.getAuthorities(); String[] authorities=new String[authorities1.size()]; authorities1.toArray(authorities); // Fill in user information and permissions To user identity token In objects UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(jwtTokenInfo.getUser_name(),null, AuthorityUtils.createAuthorityList(authorities)); authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); // Will authenticationToken Fill in the security context SecurityContextHolder.getContext().setAuthentication(authenticationToken); filterChain.doFilter(request,response); }}```### 3. Register the filter to the filter chain to modify WebSecurityConfig Class , Register the filter as follows :``` java.addFilterAfter(authFilterCustom, BasicAuthenticationFilter.class)// New filters ``` At the same time , Be sure to close session function , Otherwise, there will be context caching problems ``` java.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS);// Ban session``` The complete code is as follows :``` java @Autowired private AuthFilterCustom authFilterCustom; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf() .disable() .authorizeRequests()// .antMatchers("/r/r1").hasAuthority("p2")// .antMatchers("/r/r2").hasAuthority("p2") .antMatchers("/**").authenticated()// All requests must be authenticated .anyRequest().permitAll()// All other requests are freely accessible .and() .addFilterAfter(authFilterCustom, BasicAuthenticationFilter.class)// New filters .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS);// Ban session }```## Four 、 Other considerations certification services auth-server And resource services resource-server、 Gateway service gateway-server It's all about integration eureka client Components ## 5、 ... and 、 Before testing, you need to start each service in turn :- Start the registry register-server:[https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/register-server](https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/register-server)- Start the gate gateway-server:[https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/gateway-server](https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/gateway-server)- Start the authentication service auth-server:[https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/auth-server](https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/auth-server)- Start resource services resource-server:[https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/resource-server](https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0/resource-server)** First step , Get token** Here we use password Patterns get directly token,POST Request the following interface :[http://127.0.0.1:30000/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=zhangsan&password=123](http://127.0.0.1:30000/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=zhangsan&password=123) You can get token.** The second step , Access resources ** Request resource service through gateway r1 Interface ,GET Request the following interface :[http://127.0.0.1:8761/r1](http://127.0.0.1:8761/r1) You need to bring Header,key For `Authorization`,value The format is as follows :``` textBearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJ6aGFuZ3NhbiIsInNjb3BlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX0FQSSJdLCJleHAiOjE2MTAzNzI5MzUsImF1dGhvcml0aWVzIjpbInAxIiwicDIiXSwianRpIjoiOWQzMzRmZGMtOTcwZC00YmJkLWI2MmMtZDU4MDZkNTgzM2YwIiwiY2xpZW50X2lkIjoiYzEifQ.gZraRNeX-o_jKiH7XQgg3TlUQBpxUcXa2-qR_Treu8U``` If the corresponding result is as follows , The test passed ``` Access resources r1``` Otherwise , Will return to 401 Status code .## 6、 ... and 、 Project source code project source code :[https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0](https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0) My original blog address :[https://blog.kdyzm.cn/post/30](https://blog.kdyzm.cn/p
版权声明
本文为[itread01]所创,转载请带上原文链接,感谢
https://javamana.com/2021/01/20210114154851689v.html

  1. Centos7 one click installation of JDK1.8 shell script
  2. Mounting of file system in Linux (centos7)
  3. How does serverless deal with the resource supply demand of k8s in the offline scenario
  4. Detailed explanation of HBase basic principle
  5. Spring security oauth2.0 authentication and authorization 4: distributed system authentication and authorization
  6. Redis performance Part 5 redis buffer
  7. JavaScript this keyword
  8. Summary of Java multithreading (3)
  9. Sentry(v20.12.1) K8S 云原生架构探索, SENTRY FOR JAVASCRIPT 手动捕获事件基本用法
  10. Sentry(v20.12.1) K8S 云原生架构探索, SENTRY FOR JAVASCRIPT 手动捕获事件基本用法
  11. (10) Spring from the beginning to the end
  12. Summary of Java multithreading (2)
  13. Spring source notes! From the introduction to the source code, let you really understand the source code
  14. A stormy sunny day
  15. Zookeeper (curator), the implementation of distributed lock
  16. Show the sky! Tencent T4's core Java Dictionary (framework + principle + Notes + map)
  17. Spring boot project, how to gracefully replace the blank value in the interface parameter with null value?
  18. Spring boot project, how to gracefully replace the blank value in the interface parameter with null value?
  19. docker+mysql集群+读写分离+mycat管理+垂直分库+负载均衡
  20. docker+mysql集群+读写分离+mycat管理+垂直分库+负载均衡
  21. To what extent can I go out to work?
  22. Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案
  23. Implementation of rocketmq message sending based on JMeter
  24. How to choose the ticket grabbing app in the Spring Festival? We have measured
  25. Implementation of rocketmq message sending based on JMeter
  26. My programmer's Road: self study java
  27. My programmer's Road: self study java
  28. All in one, one article talks about the use of virtual machine VirtualBox and Linux
  29. All in one, one article talks about the use of virtual machine VirtualBox and Linux
  30. Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案
  31. [Java training project] Java ID number recognition system
  32. How does serverless deal with the resource supply demand of k8s in the offline scenario
  33. Detailed explanation of HBase basic principle
  34. Explain the function of thread pool and how to use it in Java
  35. Kubernetes official java client 8: fluent style
  36. 010_MySQL
  37. Vibrant special purchases for the Spring Festival tiktok section, hundreds of good things to make the year more rich flavor.
  38. 010_MySQL
  39. Of the 4 million docker images, 51% have high-risk vulnerabilities
  40. Rocketmq CPP client visual studio 2019 compilation
  41. Rocketmq CPP client visual studio 2019 compilation
  42. Usage of data custom attribute in jquery
  43. Common decompression in Linux
  44. Upload large files in Java
  45. Sentry (v20.12.1) k8s cloud native architecture exploration, sentry for JavaScript manual capture event basic usage
  46. Sentry (v20.12.1) k8s cloud native architecture exploration, sentry for JavaScript manual capture event basic usage
  47. Docker + MySQL Cluster + read / write separation + MYCAT Management + vertical sub database + load balancing
  48. Docker + MySQL Cluster + read / write separation + MYCAT Management + vertical sub database + load balancing
  49. Java use interceptor infinite forwarding / redirection infinite loop / redirection times too many error (stack overflow error) solution
  50. Java use interceptor infinite forwarding / redirection infinite loop / redirection times too many error (stack overflow error) solution
  51. 010_ MySQL
  52. 010_ MySQL
  53. Fast integration of imsdk and Huawei offline push
  54. 消息队列之RabbitMQ
  55. Rabbitmq of message queue
  56. 初学java进制转换方面补充学习
  57. Learn java base conversion supplementary learning
  58. 了解一下RPC,为何诞生RPC,和HTTP有什么不同?
  59. 了解一下RPC,为何诞生RPC,和HTTP有什么不同?
  60. 初学java进制转换方面补充学习