Skip to content

Commit 9887140

Browse files
committedJun 1, 2021
feat:添加网关鉴权、消息推送功能
1 parent 8943ece commit 9887140

File tree

22 files changed

+479
-0
lines changed

22 files changed

+479
-0
lines changed
 

‎world-gateway/pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
<description>epq-world 网关</description>
1717

1818
<dependencies>
19+
<dependency>
20+
<groupId>com.auth0</groupId>
21+
<artifactId>java-jwt</artifactId>
22+
<version>3.16.0</version>
23+
</dependency>
1924
<dependency>
2025
<groupId>io.springfox</groupId>
2126
<artifactId>springfox-boot-starter</artifactId>

‎world-gateway/src/main/java/icu/epq/gateway/GatewayApplication.java

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
55
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6+
import springfox.documentation.swagger2.annotations.EnableSwagger2;
67

78
/**
89
* gateway 启动器
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package icu.epq.gateway.filter;
2+
3+
import com.auth0.jwt.interfaces.DecodedJWT;
4+
import com.fasterxml.jackson.core.JsonProcessingException;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import icu.epq.gateway.provider.ResponseProvider;
7+
import icu.epq.gateway.util.JwtUtil;
8+
import lombok.AllArgsConstructor;
9+
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
10+
import org.springframework.cloud.gateway.filter.GlobalFilter;
11+
import org.springframework.core.Ordered;
12+
import org.springframework.core.io.buffer.DataBuffer;
13+
import org.springframework.http.HttpStatus;
14+
import org.springframework.http.server.reactive.ServerHttpResponse;
15+
import org.springframework.stereotype.Component;
16+
import org.springframework.web.server.ServerWebExchange;
17+
import reactor.core.publisher.Flux;
18+
import reactor.core.publisher.Mono;
19+
20+
import java.nio.charset.StandardCharsets;
21+
import java.util.Date;
22+
23+
/**
24+
* token认证过滤器
25+
*
26+
* @author epqsky
27+
*/
28+
@Component
29+
@AllArgsConstructor
30+
public class AuthFilter implements GlobalFilter, Ordered {
31+
32+
private final ObjectMapper objectMapper;
33+
34+
@Override
35+
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
36+
String path = exchange.getRequest().getURI().getPath();
37+
if (path.startsWith("/world-auth")) {
38+
return chain.filter(exchange);
39+
}
40+
41+
ServerHttpResponse response = exchange.getResponse();
42+
String authorization = exchange.getRequest().getHeaders().getFirst("Authorization");
43+
DecodedJWT jwt = JwtUtil.parseJwtToken(authorization);
44+
if (jwt == null) {
45+
return unAuth(response, "token异常");
46+
}
47+
if (jwt.getExpiresAt().compareTo(new Date()) < 0) {
48+
return unAuth(response, "token过期");
49+
}
50+
51+
return chain.filter(exchange);
52+
}
53+
54+
@Override
55+
public int getOrder() {
56+
return -100;
57+
}
58+
59+
private Mono<Void> unAuth(ServerHttpResponse resp, String msg) {
60+
resp.setStatusCode(HttpStatus.UNAUTHORIZED);
61+
resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
62+
String result = "";
63+
try {
64+
result = objectMapper.writeValueAsString(ResponseProvider.unAuth(msg));
65+
} catch (JsonProcessingException e) {
66+
System.out.println(e.getMessage());
67+
}
68+
DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
69+
return resp.writeWith(Flux.just(buffer));
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package icu.epq.gateway.handler;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import icu.epq.gateway.provider.ResponseProvider;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
8+
import org.springframework.context.annotation.Configuration;
9+
import org.springframework.core.annotation.Order;
10+
import org.springframework.core.io.buffer.DataBufferFactory;
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.http.MediaType;
13+
import org.springframework.http.server.reactive.ServerHttpRequest;
14+
import org.springframework.http.server.reactive.ServerHttpResponse;
15+
import org.springframework.lang.NonNull;
16+
import org.springframework.web.server.ResponseStatusException;
17+
import org.springframework.web.server.ServerWebExchange;
18+
import reactor.core.publisher.Mono;
19+
20+
/**
21+
* 异常处理
22+
*
23+
* @author epqsky
24+
*/
25+
@Order(-1)
26+
@Configuration
27+
@RequiredArgsConstructor
28+
public class ErrorExceptionHandler implements ErrorWebExceptionHandler {
29+
30+
private final ObjectMapper objectMapper;
31+
32+
@NonNull
33+
@Override
34+
public Mono<Void> handle(ServerWebExchange serverWebExchange, @NonNull Throwable throwable) {
35+
ServerHttpRequest request = serverWebExchange.getRequest();
36+
ServerHttpResponse response = serverWebExchange.getResponse();
37+
if (response.isCommitted()) {
38+
return Mono.error(throwable);
39+
}
40+
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
41+
if (throwable instanceof ResponseStatusException) {
42+
response.setStatusCode(((ResponseStatusException) throwable).getStatus());
43+
}
44+
return response.writeWith(Mono.fromSupplier(() -> {
45+
DataBufferFactory bufferFactory = response.bufferFactory();
46+
try {
47+
HttpStatus status = HttpStatus.BAD_GATEWAY;
48+
if (throwable instanceof ResponseStatusException) {
49+
status = ((ResponseStatusException) throwable).getStatus();
50+
}
51+
return bufferFactory.wrap(objectMapper.writeValueAsBytes(ResponseProvider.response(status.value(), buildMessage(request, throwable))));
52+
} catch (JsonProcessingException e) {
53+
e.printStackTrace();
54+
return bufferFactory.wrap(new byte[0]);
55+
}
56+
}));
57+
}
58+
59+
/**
60+
* 构建异常信息
61+
*/
62+
private String buildMessage(ServerHttpRequest request, Throwable throwable) {
63+
StringBuilder message = new StringBuilder("Failed to handle request [");
64+
message.append(request.getMethodValue());
65+
message.append(" ");
66+
message.append(request.getURI());
67+
message.append("]");
68+
if (throwable != null) {
69+
message.append(": ");
70+
message.append(throwable.getMessage());
71+
}
72+
return message.toString();
73+
}
74+
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package icu.epq.gateway.provider;
17+
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
21+
/**
22+
* 请求响应返回
23+
*
24+
* @author Chill
25+
*/
26+
public class ResponseProvider {
27+
28+
/**
29+
* 成功
30+
*
31+
* @param message 信息
32+
* @return
33+
*/
34+
public static Map<String, Object> success(String message) {
35+
return response(200, message);
36+
}
37+
38+
/**
39+
* 失败
40+
*
41+
* @param message 信息
42+
* @return
43+
*/
44+
public static Map<String, Object> fail(String message) {
45+
return response(400, message);
46+
}
47+
48+
/**
49+
* 未授权
50+
*
51+
* @param message 信息
52+
* @return
53+
*/
54+
public static Map<String, Object> unAuth(String message) {
55+
return response(401, message);
56+
}
57+
58+
/**
59+
* 服务器异常
60+
*
61+
* @param message 信息
62+
* @return
63+
*/
64+
public static Map<String, Object> error(String message) {
65+
return response(500, message);
66+
}
67+
68+
/**
69+
* 构建返回的JSON数据格式
70+
*
71+
* @param status 状态码
72+
* @param message 信息
73+
* @return
74+
*/
75+
public static Map<String, Object> response(int status, String message) {
76+
Map<String, Object> map = new HashMap<>(16);
77+
map.put("code", status);
78+
map.put("msg", message);
79+
map.put("data", null);
80+
return map;
81+
}
82+
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package icu.epq.gateway.util;
2+
3+
import javax.crypto.BadPaddingException;
4+
import javax.crypto.Cipher;
5+
import javax.crypto.IllegalBlockSizeException;
6+
import javax.crypto.NoSuchPaddingException;
7+
import javax.crypto.spec.GCMParameterSpec;
8+
import javax.crypto.spec.SecretKeySpec;
9+
import java.security.InvalidAlgorithmParameterException;
10+
import java.security.InvalidKeyException;
11+
import java.security.NoSuchAlgorithmException;
12+
import java.util.Base64;
13+
14+
/**
15+
* 加密、解密工具
16+
*
17+
* @author epqsky
18+
*/
19+
public class CryptUtil {
20+
21+
/**
22+
* 密钥
23+
*/
24+
private static final byte[] DEFAULT_SECRET_KEY = Base64.getEncoder().encode("8NJpH36GGK9a3IkyFd3l6Kb8CJkid9QJ".getBytes());
25+
26+
/**
27+
* 初始向量 VI
28+
*/
29+
private static final byte[] KEY_VI = Base64.getEncoder().encode("cs4GXOnrqLKK".getBytes());
30+
31+
/**
32+
* 字符串信息加密
33+
*
34+
* @param info
35+
* @return
36+
* @throws NoSuchPaddingException
37+
* @throws NoSuchAlgorithmException
38+
* @throws InvalidAlgorithmParameterException
39+
* @throws InvalidKeyException
40+
* @throws BadPaddingException
41+
* @throws IllegalBlockSizeException
42+
*/
43+
public static String setAes256String(String info) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
44+
SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(DEFAULT_SECRET_KEY), "AES");
45+
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
46+
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(96, Base64.getDecoder().decode(KEY_VI));
47+
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
48+
49+
return Base64.getEncoder().encodeToString(cipher.doFinal(info.getBytes()));
50+
}
51+
52+
/**
53+
* 字符串信息解密
54+
*
55+
* @param info
56+
* @return
57+
* @throws NoSuchPaddingException
58+
* @throws NoSuchAlgorithmException
59+
* @throws InvalidAlgorithmParameterException
60+
* @throws InvalidKeyException
61+
* @throws BadPaddingException
62+
* @throws IllegalBlockSizeException
63+
*/
64+
public static String getAes256String(String info) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
65+
SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(DEFAULT_SECRET_KEY), "AES");
66+
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
67+
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(96, Base64.getDecoder().decode(KEY_VI));
68+
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
69+
return new String(cipher.doFinal(Base64.getDecoder().decode(info)));
70+
}
71+
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package icu.epq.gateway.util;
2+
3+
import com.auth0.jwt.JWT;
4+
import com.auth0.jwt.algorithms.Algorithm;
5+
import com.auth0.jwt.interfaces.DecodedJWT;
6+
import com.auth0.jwt.interfaces.Verification;
7+
8+
import javax.crypto.BadPaddingException;
9+
import javax.crypto.IllegalBlockSizeException;
10+
import javax.crypto.NoSuchPaddingException;
11+
import java.security.InvalidAlgorithmParameterException;
12+
import java.security.InvalidKeyException;
13+
import java.security.NoSuchAlgorithmException;
14+
import java.util.Base64;
15+
16+
/**
17+
* jwt 工具
18+
*
19+
* @author epqsky
20+
*/
21+
public class JwtUtil {
22+
23+
/**
24+
* JWT密钥
25+
*/
26+
private static final byte[] JWT_SECRET_KEY = Base64.getEncoder().encode("QO7uI4E6yeg9rkn95Xsahl0p9HINUJN2".getBytes());
27+
28+
public static DecodedJWT parseJwtToken(String token) {
29+
30+
String accessToken;
31+
try {
32+
accessToken = CryptUtil.getAes256String(token);
33+
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
34+
return null;
35+
}
36+
37+
Verification verify = JWT.require(Algorithm.HMAC256(Base64.getDecoder().decode(JWT_SECRET_KEY)));
38+
39+
return verify.build().verify(accessToken);
40+
}
41+
42+
}

‎world-pay/pom.xml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>epq-world</artifactId>
7+
<groupId>icu.epq.epq-world</groupId>
8+
<version>0.0.1</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>world-pay</artifactId>
13+
14+
15+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.pay;
2+
3+
public class PayApplication {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.pay.config;
2+
3+
public class AliPayConfig {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.pay.config;
2+
3+
public class AliPayProperties {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.pay.controller;
2+
3+
public class PayController {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.pay.paycenter;
2+
3+
public class AliPay {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
server:
2+
port: 8082
3+
spring:
4+
application:
5+
name: world-auth
6+
cloud:
7+
nacos:
8+
discovery:
9+
server-addr: 127.0.0.1:8848
10+
config:
11+
server-addr: 127.0.0.1:8848
12+
file-extension: yaml
13+
profiles:
14+
active: dev

‎world-paypal/pom.xml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>epq-world</artifactId>
7+
<groupId>icu.epq.epq-world</groupId>
8+
<version>0.0.1</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>world-paypal</artifactId>
13+
14+
15+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package icu.epq.paypal;
2+
3+
import org.springframework.boot.autoconfigure.SpringBootApplication;
4+
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
5+
import org.springframework.scheduling.annotation.EnableAsync;
6+
7+
@SpringBootApplication(scanBasePackages = {"icu.epq.common.exception", "icu.epq.paypal"})
8+
@EnableDiscoveryClient
9+
@EnableAsync
10+
public class PaypalApplication {
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
server:
2+
port: 8082
3+
spring:
4+
application:
5+
name: world-auth
6+
cloud:
7+
nacos:
8+
discovery:
9+
server-addr: 127.0.0.1:8848
10+
config:
11+
server-addr: 127.0.0.1:8848
12+
file-extension: yaml
13+
profiles:
14+
active: dev

‎world-push/pom.xml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>epq-world</artifactId>
7+
<groupId>icu.epq.epq-world</groupId>
8+
<version>0.0.1</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>world-push</artifactId>
13+
14+
15+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.push;
2+
3+
public class PushApplication {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.push.config;
2+
3+
public class WebSocketConfig {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package icu.epq.push.controller;
2+
3+
public class WebSocketController {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
server:
2+
port: 8082
3+
spring:
4+
application:
5+
name: world-auth
6+
cloud:
7+
nacos:
8+
discovery:
9+
server-addr: 127.0.0.1:8848
10+
config:
11+
server-addr: 127.0.0.1:8848
12+
file-extension: yaml
13+
profiles:
14+
active: dev

0 commit comments

Comments
 (0)
Please sign in to comment.