package com.k5003.gatewayzuul.config;
import com.k5003.gatewayzuul.service.GatewayService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
-
统一监听jwttoken的校验
-
king 2020.05.03
*/
@Component
public class JwtTokenFilter implements GlobalFilter, Ordered {
@Autowired
GatewayService gtewayService;
//公钥
private static final String PUBLIC_KEY = "publickey.txt";
//跳过验证地址 登录等
private String[] skipAuthUrls = {"/auth/auth/userlogin","/auth/auth/v2/api-docs","/users/users/v2/api-docs","/qiniu/qiniu/v2/api-docs"};
@Override
public int getOrder() {
return -1;
}
/**
* 过滤器
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String url = exchange.getRequest().getURI().getPath();
System.out.println(url);
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
System.out.println(token);
if (null != skipAuthUrls && Arrays.asList(skipAuthUrls).contains(url)) {
return chain.filter(exchange);
}
if (StringUtils.isBlank(token)) {
return returnAuthFail(exchange, "请先登陆");
} else {
//判断是否存在cookie
String tokenFromCookie = gtewayService.getTokenFromCookie(exchange);
if(StringUtils.isEmpty(tokenFromCookie)){
//拒绝访问
//return returnAuthFail(exchange, "登录超时,请重新登录");
}
//从header中取jwt
String jwtFromHeader = gtewayService.getJwtFromHeader(exchange);
if(StringUtils.isEmpty(jwtFromHeader)){
//拒绝访问
return returnAuthFail(exchange, "异常访问,请重新登录");
}
//从redis取出jwt的过期时间
//long expire = gtewayService.getExpire(tokenFromCookie);
//if(expire<0){
//拒绝访问
//return returnAuthFail(exchange, "登录超时,请重新登录");
//}
//根据公钥校验token
Boolean isjwts=jwrVerify(token);
if(!isjwts){
//拒绝访问
return returnAuthFail(exchange, "登录异常,请重新登录");
}
return chain.filter(exchange);
}
}
/**
* 返回校验失败
*
* @param exchange
* @return
*/
private Mono<Void> returnAuthFail(ServerWebExchange exchange,String message) {
ServerHttpResponse serverHttpResponse = exchange.getResponse();
serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
String resultData = "{\"status\":\"-1\",\"msg\":"+message+"}";
byte[] bytes = resultData.getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
return exchange.getResponse().writeWith(Flux.just(buffer));
}
/**
- 校验jwt的合法性
- @param jwtString
- @return
*/
private Boolean jwrVerify(String jwtString){
Boolean jwtver=true;
String publickey=getPubKey();
//校验jwt令牌
try{
Jwt jwt = JwtHelper.decodeAndVerify(jwtString.replace(“Bearer “,””), new RsaVerifier(publickey));
} catch (Exception e) {
jwtver=false;
}
return jwtver;
}
/**
- 获取公钥字符
- @return
*/
private String getPubKey() {
Resource resource = new ClassPathResource(PUBLIC_KEY);
try {
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
BufferedReader br = new BufferedReader(inputStreamReader);
return br.lines().collect(Collectors.joining("\n"));
} catch (IOException ioe) {
return null;
}
}
}