4.2.4、添加token辅助类
package com.kelvin.common.dto; import lombok.Data; /*** * @title TokenDTO * @desctption <TODO description class purpose> * @author Administrator * @create 2023/6/8 10:01 **/ @Data public class TokenDTO { private String token; }
4.3、构建网关子工程
4.3.1、修改pom.xml配置
修改父工程指向
<parent> <groupId>com.kelvin</groupId> <artifactId>onlinestore</artifactId> <version>1.0-SNAPSHOT</version> </parent>
<dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.8.5</version> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> <version>1.8.6</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.kelvin</groupId> <artifactId>store-common</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>
4.3.2、修改application.yml配置
server: port: 80 spring: main: web-application-type: reactive application: name: gateway-service cloud: nacos: discovery: server-addr: localhost:8848 #Nacos server 的地址 gateway: #网关路由配置 routes: #将 drp-user-service 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 80 - id: user-api_routh #路由 id,没有固定规则,但唯一,建议与服务名对应 uri: lb://user-api #匹配后提供服务的路由地址 predicates: #以下是断言条件,必选全部符合条件 - Path=/user/** #断言,路径匹配 注意:Path 中 P 为大写 - Method=GET,POST #只能时 GET 请求时,才能访问 metadata: connect-timeout: 10 #单位毫秒 response-timeout: 10000 - id: authority-service_routh #路由 id,没有固定规则,但唯一,建议与服务名对应 uri: lb://auth-service #匹配后提供服务的路由地址 predicates: #以下是断言条件,必选全部符合条件 - Path=/auth/** #断言,路径匹配 注意:Path 中 P 为大写 - Method=GET,POST #只能时 GET 请求时,才能访问 metadata: connect-timeout: 10 #单位毫秒 response-timeout: 10000 sentinel: transport: #配置 Sentinel dashboard 地址 dashboard: localhost:8080 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口 port: 8719 #开启除了controller层其他链路调用 web-context-unify: false
4.3.3、网关解决跨域问题
package com.kelvin.storegateway.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsConfigurationSource; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.Arrays; @Configuration public class WebConfig { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList("GET", "POST")); configuration.setAllowedHeaders(Arrays.asList("content-type","token")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } @Bean public CorsWebFilter corsWebFilter(CorsConfigurationSource corsConfigurationSource) { return new CorsWebFilter(corsConfigurationSource); } @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true); } }; } }
4.3.4、网关增加鉴权功能AuthService
package com.kelvin.storegateway.service; import com.kelvin.common.dto.TokenDTO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.PostMapping; /*** * @title AuthService * @desctption <TODO description class purpose> * @author Administrator * @create 2023/6/8 10:04 **/ @Component @FeignClient(value = "auth-service") public interface AuthService { @PostMapping("auth/isTokenExpiration") public Boolean validateToken(TokenDTO token); }
4.3.5、增加网关登录验证拦截GatewayWebFilter
package com.kelvin.storegateway.filter; import com.kelvin.common.dto.TokenDTO; import com.kelvin.storegateway.service.AuthService; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import javax.annotation.Resource; import java.util.stream.Collectors; /*** * @title DrfGlobalFilter * @desctption 登录验证 * @author Administrator * @create 2023/5/15 14:17 **/ @Component public class GatewayWebFilter implements GlobalFilter { @Resource private AuthService authService; @Bean @ConditionalOnMissingBean public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) { return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList())); } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); //如果登录请求,不用验证token String path = request.getURI().getPath(); if(!path.contains("login")) { HttpHeaders headers = request.getHeaders(); String token = headers.getFirst("token"); if(StringUtils.isEmpty(token)) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } else { TokenDTO tokenDTO = new TokenDTO(); tokenDTO.setToken(token); //token验证不通过,返回给前端401 Boolean aBoolean = authService.validateToken(tokenDTO); if(aBoolean){ ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } } } return chain.filter(exchange); } }
4.3、构建微服务鉴权子工程store-authority-service
4.4、构建微服务提供服务方子工程store-api
4.5、构建微服务调用方子工程store-user-service
小结
通过上述操作可以轻松搭建出微服务架构,扩展十分容易。
父子工程构建已可用,持续更新中…