软件系统定制开发本文主要内容是通过SpringCloud Gateway
软件系统定制开发构建一个微服务,软件系统定制开发作为统一的认证授权和访问入口。
配置文件
先引入相关依赖,对应的pom文件内容如下:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>oauth2-demo</artifactId> <groupId>com.zjq</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>ms-gateway</artifactId> <dependencies> <!-- spring cloud gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- eureka client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- commons 公共项目 --> <dependency> <groupId>com.zjq</groupId> <artifactId>commons</artifactId> <version>1.0-SNAPSHOT</version> <!-- 和 webflux 冲突 --> <exclusions> <exclusion> <groupId>com.battcn</groupId> <artifactId>swagger-spring-boot-starter</artifactId> </exclusion> </exclusions> </dependency> <!-- 自定义的元数据依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies></project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
网关服务的yml配置内容如下:
server: port: 80spring: application: name: ms-gateway cloud: gateway: discovery: locator: enabled: true # 开启配置注册中心进行路由功能 lower-case-service-id: true # 将服务名称转小写 routes: - id: ms-users uri: lb://ms-users predicates: - Path=/users/** filters: - StripPrefix=1 - id: ms-oauth2-server uri: lb://ms-oauth2-server predicates: - Path=/auth/** filters: - StripPrefix=1secure: ignore: urls: # 配置白名单路径 - /actuator/** - /auth/oauth/** - /users/signin# 配置 Eureka Server 注册中心eureka: instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} client: service-url: defaultZone: http://localhost:7000/eureka/logging: pattern: console: '%d{HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
请求白名单配置
加载配置文件中的配置,注入到spring容器中。
secure: ignore: urls: # 配置白名单路径 - /actuator/** - /auth/oauth/** - /users/signin
- 1
- 2
- 3
- 4
- 5
- 6
/** * 网关白名单配置 * @author zjq */@Data@Component@ConfigurationProperties(prefix = "secure.ignore")public class IgnoreUrlsConfig { private List<String> urls;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
异常处理和rest请求配置
异常处理在全局过滤器中会有用到,代码如下:
@Componentpublic class HandleException { @Resource private ObjectMapper objectMapper; public Mono<Void> writeError(ServerWebExchange exchange, String error) { ServerHttpResponse response = exchange.getResponse(); ServerHttpRequest request = exchange.getRequest(); response.setStatusCode(HttpStatus.OK); response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); ResultInfo resultInfo = ResultInfoUtil.buildError(ApiConstant.NO_LOGIN_CODE, ApiConstant.NO_LOGIN_MESSAGE, request.getURI().getPath()); String resultInfoJson = null; DataBuffer buffer = null; try { resultInfoJson = objectMapper.writeValueAsString(resultInfo); buffer = response.bufferFactory().wrap(resultInfoJson.getBytes(Charset.forName("UTF-8"))); } catch (JsonProcessingException ex) { ex.printStackTrace(); } return response.writeWith(Mono.just(buffer)); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
申请授权和认证过程中需要远程调用其他接口,所以我们引入rest请求配置,代码如下:
/** * REST请求配置 * @author zjq */@Configurationpublic class RestTemplateConfiguration { @LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
全局过滤器配置
配置好了白名单,我们需要在网关过滤器中使用该白名单配置,放行对应的白名单,网关过滤器需要实现全局过滤器接口org.springframework.cloud.gateway.filter.GlobalFilter
和过滤器顺序接口org.springframework.core.Ordered
相关代码如下:
/** * 网关全局过滤器 * @author zjq */@Componentpublic class AuthGlobalFilter implements GlobalFilter, Ordered { @Resource private IgnoreUrlsConfig ignoreUrlsConfig; @Resource private RestTemplate restTemplate; @Resource private HandleException handleException; /** * 身份校验处理 * * @param exchange * @param chain * @return */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 判断当前的请求是否在白名单中 AntPathMatcher pathMatcher = new AntPathMatcher(); boolean flag = false; String path = exchange.getRequest().getURI().getPath(); for (String url : ignoreUrlsConfig.getUrls()) { if (pathMatcher.match(url, path)) { flag = true; break; } } // 白名单放行 if (flag) { return chain.filter(exchange); } // 获取 access_token String access_token = exchange.getRequest().getQueryParams().getFirst("access_token"); // 判断 access_token 是否为空 if (StringUtils.isBlank(access_token)) { return handleException.writeError(exchange, "请登录"); } // 校验 token 是否有效 String checkTokenUrl = "http://ms-oauth2-server/oauth/check_token?token=".concat(access_token); try { // 发送远程请求,验证 token ResponseEntity<String> entity = restTemplate.getForEntity(checkTokenUrl, String.class); // token 无效的业务逻辑处理 if (entity.getStatusCode() != HttpStatus.OK) { return handleException.writeError(exchange, "Token was not recognised, token: ".concat(access_token)); } if (StringUtils.isBlank(entity.getBody())) { return handleException.writeError(exchange, "This token is invalid: ".concat(access_token)); } } catch (Exception e) { return handleException.writeError(exchange, "Token was not recognised, token: ".concat(access_token)); } // 放行 return chain.filter(exchange); } /** * 网关过滤器的排序,数字越小优先级越高 * * @return */ @Override public int getOrder() { return 0; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
测试验证
登录:
获取当前登录用户信息:
退出登录:
本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位指出。
主页:保持热爱,奔赴下一场山海。🏃🏃🏃