服务网关(Gateway)自定义全局过滤器&统一Token处理
* 代码繁琐,每个Controller都需要获取token,验证用户是否登录* token解析不方便
·
网关登录校验
在网关工程中添加全局过滤器
import com.alibaba.fastjson.JSON;
import com.xuecheng.commons.model.vo.AuthInfo;
import com.xuecheng.commons.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.SneakyThrows;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.URLEncoder;
/**
* 网关-全局过滤器
* 1、实现两个接口和两个方法
* 2、在filter方法中,完成过滤逻辑
*/
@Component
public class AuthFilter implements GlobalFilter, Ordered {
/**
* 核心过滤方法:业务处理
* @param exchange:请求上下文(获取request和response)
* @param chain:过滤器链(控制程序放行)
* @return
*/
@SneakyThrows
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//1、获取当前的请求连接
String path = request.getURI().getPath();
//2、判断,此请求地址是否需要进行token校验,如果不需要,直接放行,进入微服务
if(path.contains("coursePub/preview") ||
path.contains("login") ||
path.contains("basic/dictionary") ||
path.contains("category/tree-nodes")||
path.contains("course/upload")||
path.contains("search/")){
return chain.filter(exchange);
}
//3、获取请求头参数token
String token = request.getHeaders().getFirst("Authorization");
Boolean verifyToken = JwtUtils.verifyToken(token);
//4、验证token是否合法,如果不合法,响应状态码401
if(!verifyToken) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete(); //直接返回
}
//5、解析token,获取登录时存入的数据(userId,companyId,companyName)
Claims claims = JwtUtils.parserToken(token).getBody();
Long userId = claims.get("userId", Long.class);
Long companyId = claims.get("companyId", Long.class);
String companyName = claims.get("companyName", String.class);
//转化java对象
AuthInfo info = new AuthInfo();
info.setUid(userId);
info.setCompanyName(companyName);
info.setCompanyId(companyId);
//6、设置一个新的请求头参数(解析后的明文数据)
String json = URLEncoder.encode(JSON.toJSONString(info),"UTF-8");
//创建一个httpRequest的请求对象
ServerHttpRequest httpRequest = request.mutate().headers(httpHeaders -> {
httpHeaders.set("payload", json);
}).build();
//将此请求对象,写入到微服务转发的上下文中
exchange.mutate().request(httpRequest);
return chain.filter(exchange);
}
/**
* 指定多个过滤器时,此过滤器的执行顺序
*/
public int getOrder() {
return 0;
}
}
统一token解析(添加到微服务当中或提取出来)
编写拦截器
import com.alibaba.fastjson.JSON;
import com.xuecheng.commons.model.vo.AuthInfo;
import com.xuecheng.commons.utils.AuthInfoHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
/**
* 自定义拦截器
*/
@Component
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {
//进入controller方法之前执行。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1、获取网关转发来的json数据,
String payload = request.getHeader("payload");
if(StringUtils.isEmpty(payload)) {
return true; //执行controller
}
//2、转化成AuthInfo对象,
String json = URLDecoder.decode(payload, "UTF-8");
log.info("json = " + json);
AuthInfo info = JSON.parseObject(json, AuthInfo.class);
log.info("info = " + info);
//3、存入threadlocal
AuthInfoHolder.setAuthInfo(info);
return true;
}
//执行controller方法之后执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
//响应结束之前
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
配置拦截器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//配置类,注册拦截器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TokenInterceptor()) // 添加拦截器
.addPathPatterns("/**"); // 添加拦截的路径
}
}
ThreadLocal工具类
import com.xuecheng.commons.model.vo.AuthInfo;
/**
* 存放用户id的容器
*/
public class AuthInfoHolder {
private final static ThreadLocal<AuthInfo> threadLocal = new ThreadLocal<>();
/**
* 获取线程中的用户
*/
public static AuthInfo getAuthInfo() {
return threadLocal.get();
}
/**
* 设置当前线程中的用户
*/
public static void setAuthInfo(AuthInfo info) {
threadLocal.set(info);
}
public static Long getUserId() {
return threadLocal.get().getUid();
}
public static Long getCompanyId() {
if(threadLocal.get() != null) {
return threadLocal.get().getCompanyId();
}else {
return null;
}
}
public static void remove(){threadLocal.remove();}
}
更多推荐
已为社区贡献2条内容
所有评论(0)