基于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;
    }
}
相关推荐
小羊没烦恼!5 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里5 天前
java中的继承和多态的区别
java
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕5 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码5 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖5 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时5 天前
01-06-A-JVM排查实战详解
java·jvm
vipxieliang5 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi5 天前
mysql 查询所有表名并授权
java
ProcessOn官方账号5 天前
java函数式编程--入门基础
java·编程·函数式编程