#957·Sa-Token

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 里单独认证的。希望后期这个白名单也可以做成动态的 还是读之前的值 感觉是首次只初始化了一次 既然框架有白名单的功能 不想下沉在做一次了

应用场景阐述:

< 备注:请尽量详细描述功能应用场景 >