广州市综治平台后端
xusd
2025-06-07 36306491396230522fa20585c2621a7fc899849a
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package cn.huge.gateway.filter;
 
import cn.huge.gateway.utils.JsonMapper;
import cn.huge.gateway.utils.ReturnBO;
import cn.huge.gateway.utils.SpringContextUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
 
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * @title: 网关拦截器
 * @description: 网关拦截器
 * @company: hugeinfo
 * @author: liyj
 * @time: 2021-11-05 16:51:48
 * @version: 1.0.0
 */
@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {
 
    @Value("${jwt.secret-key}")
    private String secretKey;
 
    @Value("${jwt.iss-user}")
    private String issUser;
 
    @Value("${jwt.auth-skip-urls}")
    private String[] skipAuthUrls;
 
    @Value("${jwt.blacklist-key.format}")
    private String jwtBlacklistKeyFormat;
 
    @Override
    public int getOrder() {
        return -100;
    }
 
    /**
     * 拦截方法
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getURI().getPath();
        //跳过不需要验证的路径
        List<String> skipAuthUrlList = Arrays.asList(skipAuthUrls);
        Boolean status = false;
        if (!CollectionUtils.isEmpty(skipAuthUrlList)) {
            for (String skipAuthUrl : skipAuthUrlList) {
                if (url.indexOf(skipAuthUrl) != -1) {
                    status = true;
                    break;
                }
            }
        }
        if (status) {
            return chain.filter(exchange);
        } else {
            JsonMapper jsonMapper = new JsonMapper();
            ReturnBO returnBO = new ReturnBO();
            //从请求头中取出token
            String token = exchange.getRequest().getHeaders().getFirst("Authorization");
            //未携带token或token在黑名单内
            if (StringUtils.isEmpty(token) || isBlackToken(token)) {
                ServerHttpResponse originalResponse = exchange.getResponse();
                originalResponse.setStatusCode(HttpStatus.OK);
                originalResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
                returnBO.setCode(401);
                returnBO.setMsg("您尚未登录,请登录后重试!");
                byte[] response = jsonMapper.toJson(returnBO).getBytes(StandardCharsets.UTF_8);
                DataBuffer buffer = originalResponse.bufferFactory().wrap(response);
                return originalResponse.writeWith(Flux.just(buffer));
            } else {
                //取出token包含的身份
                returnBO = verifyJWT(token);
                if (returnBO.getCode() != 0) {
                    ServerHttpResponse originalResponse = exchange.getResponse();
                    originalResponse.setStatusCode(HttpStatus.OK);
                    originalResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
                    byte[] response = jsonMapper.toJson(returnBO).getBytes(StandardCharsets.UTF_8);
                    DataBuffer buffer = originalResponse.bufferFactory().wrap(response);
                    return originalResponse.writeWith(Flux.just(buffer));
                } else {
                    //将现在的request,添加当前身份
                    String userId = (String) returnBO.getData();
                    ServerHttpRequest mutableReq = null;
                    exchange.getRequest().mutate().header("Authorization-userId", userId).build();
                    ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
                    return chain.filter(mutableExchange);
                }
            }
        }
    }
 
    /**
     * JWT验证
     * @param token 授权信息
     * @return Map
     */
    private ReturnBO verifyJWT(String token){
        ReturnBO returnBO = new ReturnBO();
        try {
            Algorithm algorithm = Algorithm.HMAC256(secretKey);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(issUser)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            String userId = jwt.getClaim("userId").asString();
            if (userId.isEmpty()){
                returnBO.setCode(401);
                returnBO.setMsg("您尚未登录,请登录后重试!");
            }else{
                returnBO.setCode(0);
                returnBO.setData(userId);
            }
        } catch (JWTVerificationException e){
            log.error("AuthFilter方法[verifyJWT]调用异常:"+e, e);
            if (e.getMessage().indexOf("The Token has expired") != -1){
                returnBO.setCode(401);
                returnBO.setMsg("您尚未登录,请登录后重试!");
            }else{
                returnBO.setCode(401);
                returnBO.setMsg("您尚未登录,请登录后重试!");
            }
        }
        return returnBO;
    }
 
    /**
     * 判断token是否在黑名单内
     * @param token 授权信息
     * @return boolean
     */
    private boolean isBlackToken(String token){
        assert token != null;
//        return stringRedisTemplate.hasKey(String.format(jwtBlacklistKeyFormat, token));
        return false;
    }
 
    /**
     * usi追加custId
     * @param uri uri
     * @param custId custId参数
     * @return
     * @throws UnsupportedEncodingException
     */
    private URI assembleUri(URI uri, String custId) {
        StringBuilder query = new StringBuilder();
        //追加custId参数
        if(query.length() != 0){
            query.append("&");
        }
        query.append("custId=");
        query.append(custId);
        //转码,生成新的URI
        URI newUri = UriComponentsBuilder.fromUri(uri).replaceQuery(query.toString()).build(true).toUri();
        return newUri;
    }
}
/**
 * -------------------_ooOoo_-------------------
 * ------------------o8888888o------------------
 * ------------------88" . "88------------------
 * ------------------(| -_- |)------------------
 * ------------------O\  =  /O------------------
 * ---------------____/`---'\____---------------
 * -------------.'  \\|     |//  `.-------------
 * ------------/  \\|||  :  |||//  \------------
 * -----------/  _||||| -:- |||||-  \-----------
 * -----------|   | \\\  -  /// |   |-----------
 * -----------| \_|  ''\---/''  |   |-----------
 * -----------\  .-\__  `-`  ___/-. /-----------
 * ---------___`. .'  /--.--\  `. . __----------
 * ------."" '<  `.___\_<|>_/___.'  >'"".-------
 * -----| | :  `- \`.;`\ _ /`;.`/ - ` : | |-----
 * -----\  \ `-.   \_ __\ /__ _/   .-` /  /-----
 * ======`-.____`-.___\_____/___.-`____.-'======
 * -------------------`=---='
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 * ---------佛祖保佑---hugeinfo---永无BUG----------
 */