基于SpringCloudGateway实现接口鉴权

一、在pom.xml中导入SpringCloudGateway jar包

XML 复制代码
dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

二、在application.yaml中配置接口路径

java 复制代码
url-auth:
  whitelist:
    - /demo/login
    - /demo/captcha

三、属性配置类

java 复制代码
@Data
@Configuration
@ConfigurationProperties(prefix = "url-auth")
public class UrlAuthProperties {
    /***白名单,不做鉴权处理,只做简单的业务处理*/
    private List<String> whitelist=new ArrayList<>();
    /**
     * 黑名单
     */
    private List<String> blacklist  = new ArrayList<>();
    /**
     * 忽略名单,不做任何处理
     */
    private List<String> ignoreList = new ArrayList<>();
}

四、封装基础拦截器

java 复制代码
/**
 * 基础拦截器
 *
 */
@Slf4j
public abstract class BaseFilter implements GlobalFilter, Ordered {
    @Autowired
    private UrlAuthProperties urlAuthProperties;
    /**
     * 白名单校验
     */
    public boolean isWhitelist(ServerHttpRequest request) {
        boolean result = false;
        String path = request.getPath().toString();
        HttpMethod httpMethod = request.getMethod();
        if (httpMethod != null && httpMethod.name().equals(HttpMethod.OPTIONS.name())) {
        	result = true;
        } else if (StringUtils.isNotBlank(path)) {
            List<String> urls = urlAuthProperties.getWhitelist();
            result = matchUrl(urls,path);
        }
        if(result == true) {
        	log.info("path:{}, whitelist:{}", path, result);
        }
        return result;
    }
    
    /**
     * antPathMatcher.match("/user/*", "/user/a"); 
     * antPathMatcher.match("/user/**", "/user/a/b"); 
     * antPathMatcher.match("/user/name", "/user/a");
     * antPathMatcher.isPattern("user/{id}");
     * @param urls
     * @param path
     * @return
     */
    private Boolean matchUrl(List<String> urls,String path) {
    	AntPathMatcher antPathMatcher = new AntPathMatcher(); 
    	for (Iterator<String> iterator = urls.iterator(); iterator.hasNext();) {
			String string = (String) iterator.next();
			if(string.equals(path) || antPathMatcher.match(string, path)) {
				return true;
			}
		}
		return false;
    }

    /**
     * 忽略列表处理
     */
    public boolean isIgnoreList(ServerHttpRequest request) {
        boolean result = false;
        String path = request.getPath().toString();
        HttpMethod httpMethod = request.getMethod();
        if (httpMethod != null && httpMethod.name().equals(HttpMethod.OPTIONS.name())) {
            result = true;
        } else if (StringUtils.isNotBlank(path)) {
            List<String> urls = urlAuthProperties.getIgnoreList();
            return urls.contains(path);
        }
        log.debug("path:{}, IgnoreList:{}", path, result);
        return result;
    }

    /**
     * 黑名单校验
     * 在黑名单中的请求链接将返回true
     */
    public boolean isBlacklist(ServerHttpRequest request) {
        boolean result = false;
        String path = request.getPath().toString();
        HttpMethod httpMethod = request.getMethod();
        if (httpMethod != null && httpMethod.name().equals(HttpMethod.OPTIONS.name())) {
            result = true;
        } else if (StringUtils.isNotBlank(path)) {
            List<String> urls = urlAuthProperties.getBlacklist();
            return urls.contains(path);
        }
        log.debug("path:{},blacklist:{}", path, result);
        return result;
    }

    /***从当前请求(请求头/cookie)获取授权参数*/
    public String getFromHeaderAndCookie(ServerHttpRequest request, String key) {
        HttpHeaders headers = request.getHeaders();
        // 1.从请求头中获取
        String paramValue = headers.getFirst(key);
        if (StrUtil.isBlank(paramValue)) {
            // 2.从cookie中获取
            MultiValueMap<String, HttpCookie> cookies = request.getCookies();
            HttpCookie cookie = cookies.getFirst(key);
            paramValue = Optional.ofNullable(cookie).map(HttpCookie::getValue).orElse(null);
        }
        return paramValue;
    }
}

五、实际接口拦截入口

java 复制代码
@Slf4j
@Component
public class SecurityFilter extends BaseFilter {
    private static final String AUTHORIZATION = "Authorization";
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // 白名单直接放行不做token校验
        if (isWhitelist(request)) {
            return chain.filter(exchange);
        }
        String authorization = getFromHeaderAndCookie(request, AUTHORIZATION);
        if (StringUtils.isBlank(authorization) || JwtUtils.isExpire(authorization)) {
            throw new BusinessException(CommonErrorEnum.UNAUTHORIZED);
        }

        LoginContext loginContext = JwtUtils.getCurrentUser(authorization);
        loginContext.setClientType(ClientType.ADMIN);
        LoginContextHolder.set(loginContext);

        String text = JSON.toJSONString(loginContext);
        log.info("LoginContext:{}", text);
        String unicode = UnicodeUtil.toUnicode(text, true);
        String[] headerValues = new String[]{unicode};

        ServerHttpRequest newRequest = exchange.getRequest().mutate()
                .header(LoginContextConst.LOGIN_USER, headerValues)
                .header(LoginContextConst.TOKEN, authorization).build();
        //构建新的ServerWebExchange实例
        ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();

        return chain.filter(newExchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
相关推荐
逸狼24 分钟前
【JavaEE进阶】Spring DI
java·开发语言
m0_7482486524 分钟前
SpringBoot整合easy-es
spring boot·后端·elasticsearch
yonuyeung27 分钟前
代码随想录算法【Day54】
java·数据结构·算法
敲上瘾33 分钟前
基础dp——动态规划
java·数据结构·c++·python·算法·线性回归·动态规划
my_styles1 小时前
2025-alibaba-Sentinel组件
java·开发语言·sentinel
Dongwoo Jeong1 小时前
类型系统下的语言分类与类型系统基础
java·笔记·python·lisp·fortran·type
肖帆咪1 小时前
deepseek自动化代码生成
java·ai·自动化·ai编程·deepseek
web150854159351 小时前
超级详细Spring AI运用Ollama大模型
人工智能·windows·spring
刘小炮吖i1 小时前
Java 集合:单列集合和双列集合的深度剖析
java·集合