Spring Cloud Gateway+Spring Security OAuth2+JWT(二)
Spring Cloud Gateway+Spring Security OAuth2+JWT(二)前言Gateway校验token服务获取token效果前言上一篇搭建了授权服务,这篇我们来讲讲网关。Gateway校验token我们的目标是校验token并将其解密之后传给服务package com.ljl.filter;import com.alibaba.fastjson.JSONO...
·
Spring Cloud Gateway+Spring Security OAuth2+JWT(二)
前言
上一篇搭建了授权服务,这篇我们来讲讲网关。
Gateway校验token
我们的目标是校验token并将其解密之后传给服务。
校验token jwt有自带的。其实自己也能实现。jwt由3部分组成都有一个点分隔。
原理是第一部分base64加密 加上一个点 再加上第二部分的base64加密 利用私钥签名。
所以我们只要验第三部分,利用RSA公钥验签就行了。
package com.ljl.filter;
import com.alibaba.fastjson.JSONObject;
import com.ljl.common.util.RSAUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import org.apache.commons.lang.StringUtils;
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.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import static com.ljl.common.util.RSAUtil.verify;
import static com.sun.scenario.Settings.set;
import static java.security.KeyRep.Type.SECRET;
import static org.bouncycastle.crypto.tls.SignatureAlgorithm.rsa;
/**
* Created by Administrator on 2019/9/9 0009.
*/
@Component
public class JwtTokenFilter implements GlobalFilter,Ordered {
private String[] skipAuthUrls = {"/ljl-auth/oauth/token"};
//需要从url中获取token
private String[] urlToken = {"/ljl-server-chat/websocket"};
/**
* 过滤器
*
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String url = exchange.getRequest().getURI().getPath();
System.out.println(url);
//跳过不需要验证的路径
if (null != skipAuthUrls && Arrays.asList(skipAuthUrls).contains(url)) {
return chain.filter(exchange);
}
//获取token
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if(null != urlToken && Arrays.asList(urlToken).contains(url)){
//该方法需要修改
String tokens[] = exchange.getRequest().getURI().getQuery().split("=");
token = tokens[1];
}
if (StringUtils.isBlank(token)) {
//没有token
return returnAuthFail(exchange, "请登陆");
} else {
//有token
try {
//解密token
Claims jwt = getTokenBody(token);
ServerHttpRequest oldRequest= exchange.getRequest();
URI uri = oldRequest.getURI();
ServerHttpRequest newRequest = oldRequest.mutate().uri(uri).build();
// 定义新的消息头
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
headers.remove("Authorization");
headers.set("Authorization",jwt.toString());
newRequest = new ServerHttpRequestDecorator(newRequest) {
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(headers);
return httpHeaders;
}
};
return chain.filter(exchange.mutate().request(newRequest).build());
/*System.out.println(jwt.toString());
//RSA公钥验签
String jwtData[] = token.split("\\.");
Boolean isSgin = RSAUtil.verify((jwtData[0]+"."+jwtData[1]).getBytes(),jwtData[2]);
if(isSgin){
return chain.filter(exchange);
}else{
return returnAuthFail(exchange,"token验签失败");
}*/
}catch (ExpiredJwtException e) {
e.printStackTrace();
return returnAuthFail(exchange,"token超时");
}catch (Exception e) {
e.printStackTrace();
return returnAuthFail(exchange,"token验签失败");
}
}
}
/**
* 返回校验失败
*
* @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));
}
private static Claims getTokenBody(String token){
return Jwts.parser()
.setSigningKey(RSAUtil.getPublicKey())
.parseClaimsJws(token)
.getBody();
}
@Override
public int getOrder() {
return -201;
}
}
服务获取token
这样我们就能够拿到我们的保存在token中的用户信息
/**
* 根据 id 查询 基础数据
* @param id 基础数据 id
* @return
*/
@RequestMapping(value="getBasicDataBy",method={RequestMethod.GET})
@ApiOperation(value="查询基础数据", httpMethod="GET", notes="查询基础数据", produces="application/json; charset=utf-8")
@ResponseBody
public List getBasicDataBy(@ApiParam(required=true,value="id") @RequestParam(value="id",required=true)String id, HttpServletRequest request) {
String str = request.getHeader("Authorization");
System.out.println(str);
return basicDataService.getBasicDataBy(id);
}
效果
我用的password的模式。
我们先获取token 记得密码和client_secret 都是BCrypt过的,数据库存储的是加密之后的数据。
之后我们那token去请求服务接口
好了 初步的搭建已经完成了。不过也有很多没完成。
更多推荐
已为社区贡献5条内容
所有评论(0)