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;
 }
 }
 
}