网关登录校验
在网关工程中添加全局过滤器
import com.alibaba.fastjson.JSON;import mons.model.vo.AuthInfo;import mons.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 .URLEncoder;/*** 网关-全局过滤器* 1、实现两个接口和两个方法* 2、在filter方法中,完成过滤逻辑*/@Componentpublic class AuthFilter implements GlobalFilter, Ordered {/*** 核心过滤方法:业务处理* @param exchange:请求上下文(获取request和response)* @param chain:过滤器链(控制程序放行)* @return*/@SneakyThrowspublic 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、获取请求头参数tokenString token = request.getHeaders().getFirst("Authorization");Boolean verifyToken = JwtUtils.verifyToken(token);//4、验证token是否合法,如果不合法,响应状态码401if(!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 mons.model.vo.AuthInfo;import mons.utils.AuthInfoHolder;import lombok.extern.slf4j.Slf4j;import org.ponent;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 .URLDecoder;/*** 自定义拦截器*/@Component@Slf4jpublic 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、存入threadlocalAuthInfoHolder.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;//配置类,注册拦截器@Configurationpublic class InterceptorConfig implements WebMvcConfigurer {//注册拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TokenInterceptor()) // 添加拦截器.addPathPatterns("/**"); // 添加拦截的路径}}
ThreadLocal工具类
import mons.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();}}