Satoken 配置白名单只生效一次
Author: chenliang21210909Created Jul 16, 2026Updated Aug 10, 2026
建议增加的新功能:
目前 我在使用satoken 和gateway 整合的时候遇到一个问题 我在使用satoken filter 的时候设置白名单的时候 是从nacos 取的动态的url 路径 但是 我频繁的更新我的nacos 配置 但是拦截器没有起作用 代码如下
public SaReactorFilter getSaReactorFilter(IgnoreUrlsConfig ignoreUrlsConfig) {
return new SaReactorFilter()
// 拦截地址
.addInclude("/**")
// 配置白名单路径
.setExcludeList(ignoreUrlsConfig.getUrls())
// 鉴权方法:每次访问进入
.setAuth(obj -> {
// 对于OPTIONS预检请求直接放行
SaRouter.match(SaHttpMethod.OPTIONS).stop();
//登录认证 app端 遗留个问题 app的端的token 是否可以访问小程序 目前是可以 如果 需要进行隔离 前缀需要分开 并且校验loginType 参考 ipad 和助手端
SaRouter.match(SystemType.SYSTEM_APP, r -> StpAppUtil.checkLogin()).stop();
// 登录认证:认证门店端 to-do 统一配置 //门店端新增餐饮登录认证
SaRouter.match(SystemType.SYSTEM_STORE, r -> {
StpUtil.checkLogin();
String loginType = StpUtil.getLoginType();
if (StringUtils.equals(loginType, "STORE_WEB")){throw NotLoginException.newInstance("STORE_WEB", "STORE_WEB", "请先登录", null);}
}).stop();
// 登录认证:认证 门店端 餐饮
SaRouter.match(SystemType.STORE_INDUSTRY, r -> {
StpUtil.checkLogin();
String loginType = StpUtil.getLoginType();
if (StringUtils.equals(loginType, "STORE_INDUSTRY")){throw NotLoginException.newInstance("STORE_INDUSTRY", "STORE_INDUSTRY", "请先登录", null);}
}).stop();
// 登录认证:认证 平台端
SaRouter.match(SystemType.SYSTEM_PORTAL, r -> StpPortalUtil.checkLogin()).stop();
//助手端认证
SaRouter.match(SystemType.ASSISTANT, r -> {
StpIPadUtil.checkLogin();
String loginType = StpIPadUtil.getLoginType();
if (StringUtils.equals(loginType, "PA")){throw NotLoginException.newInstance("PA", "PA", "请先登录", null);}
} ).stop();
//ipad 端登录认证
SaRouter.match(SystemType.IPAD, r -> {
StpIPadUtil.checkLogin();
String loginType = StpIPadUtil.getLoginType();
if(StringUtils.equals(loginType, "IPAD")){
throw NotLoginException.newInstance("IPAD", "IPAD", "请先登录", null);
}
}).stop();
//对于通过微服务 没有平台名称的不允许访问
throw new NotPermissionException("非法路径 不允许访问");
})
// setAuth方法异常处理
.setError(this::handleException);
}白名单的路径是我从nacos 里取的 但是 nacos 自动刷新的时候 拦截器没有起作用
以下是我的修复如下
package com.yeqiao.gateway.config;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.yeqiao.gateway.constant.SystemType;
import com.yeqiao.gateway.util.StpAppUtil;
import com.yeqiao.gateway.util.StpIPadUtil;
import com.yeqiao.gateway.util.StpPortalUtil;
import com.yeqiao.gateway.util.StringUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import java.util.*;
/**
* <p>
* Sa-Token 权限认证配置类
* </p>
*
* @author yeqiao
* @since 2022-04-27
*/
@Configuration
public class SaTokenConfig {
@Bean
public SaReactorFilter getSaReactorFilter(IgnoreUrlsConfig ignoreUrlsConfig) {
return new SaReactorFilter()
// 拦截地址
.addInclude("/**")
// 鉴权方法:每次访问进入
.setAuth(obj -> {
// 对于OPTIONS预检请求直接放行
SaRouter.match(SaHttpMethod.OPTIONS).stop();
SaRouter.match("/**").notMatch(ignoreUrlsConfig.getUrls()).check( ts -> {
//登录认证 app端 遗留个问题 app的端的token 是否可以访问小程序 目前是可以 如果 需要进行隔离 前缀需要分开 并且校验loginType 参考 ipad 和助手端
SaRouter.match(SystemType.SYSTEM_APP, r -> StpAppUtil.checkLogin()).stop();
// 登录认证:认证门店端 to-do 统一配置 //门店端新增餐饮登录认证
SaRouter.match(SystemType.SYSTEM_STORE, r -> {
StpUtil.checkLogin();
String loginType = StpUtil.getLoginType();
if (StringUtils.equals(loginType, "STORE_WEB")){throw NotLoginException.newInstance("STORE_WEB", "STORE_WEB", "请先登录", null);}
}).stop();
// 登录认证:认证 门店端 餐饮
SaRouter.match(SystemType.STORE_INDUSTRY, r -> {
StpUtil.checkLogin();
String loginType = StpUtil.getLoginType();
if (StringUtils.equals(loginType, "STORE_INDUSTRY")){throw NotLoginException.newInstance("STORE_INDUSTRY", "STORE_INDUSTRY", "请先登录", null);}
}).stop();
// 登录认证:认证 平台端
SaRouter.match(SystemType.SYSTEM_PORTAL, r -> StpPortalUtil.checkLogin()).stop();
//助手端认证
SaRouter.match(SystemType.ASSISTANT, r -> {
StpIPadUtil.checkLogin();
String loginType = StpIPadUtil.getLoginType();
if (StringUtils.equals(loginType, "PA")){throw NotLoginException.newInstance("PA", "PA", "请先登录", null);}
} ).stop();
//ipad 端登录认证
SaRouter.match(SystemType.IPAD, r -> {
StpIPadUtil.checkLogin();
String loginType = StpIPadUtil.getLoginType();
if(StringUtils.equals(loginType, "IPAD")){
throw NotLoginException.newInstance("IPAD", "IPAD", "请先登录", null);
}
}).stop();
//对于通过微服务 没有平台名称的不允许访问
throw new NotPermissionException("非法路径 不允许访问");
});
})
// setAuth方法异常处理
.setError(this::handleException);
}
private SaResult handleException(Throwable e) {
//设置错误返回格式为JSON
ServerWebExchange exchange = SaReactorSyncHolder.getContext();
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
response.getHeaders().setAccessControlAllowOrigin("*");
response.getHeaders().setCacheControl("no-cache");
SaResult result;
if(e instanceof NotLoginException){
result = new SaResult(401, "请先登录",null);
}else if(e instanceof NotPermissionException){
result = new SaResult(403, "没有权限访问",null);
}else{
result = new SaResult(500, "内部错误",e.getMessage());
}
return result;
}
}在auth 里单独认证的。希望后期这个白名单也可以做成动态的 还是读之前的值 感觉是首次只初始化了一次 既然框架有白名单的功能 不想下沉在做一次了
应用场景阐述:
< 备注:请尽量详细描述功能应用场景 >
Source: dromara/Sa-Token