基于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;
    }
}
相关推荐
码农颜7 小时前
5.4.1 锁分类
java·数据库·mysql
linux-hzh8 小时前
百日算法修炼 · Day 03
java·算法
不负岁月无痕8 小时前
简单理解操作系统结构
java·linux·c语言·开发语言·c++·面试
mister_guo9 小时前
Java线程池参数应该如何设置(ThreadPoolExecutor)
java
余额瞒着我当琳9 小时前
C++模板初阶与STL初探
android·java·c++
淡海水9 小时前
15-02-YooAsset面试篇-Unity架构设计与源码
java·unity·面试·c#·游戏引擎·yooasset
qq_448011169 小时前
C语言中的指针函数和函数指针
java·c语言·开发语言
weixin_BYSJ19879 小时前
springboot酒店管理系统--附源码27436
java·spring boot·python·随机森林·贪心算法·eclipse·django
2401_894915539 小时前
GEO 源码部署如何实现精准地域分发?核心配置参数深度讲解
java·运维·服务器·后端·开源
evans在进步11 小时前
LeetCode 2 两数相加:链表模拟加法,Java 图解进位过程
java·leetcode·链表