anonymous() 只允许未认证用户访问并创建匿名令牌,已登录用户会因权限不足报403;permitAll() 才是真正免检放行,跳过所有认证授权检查。

匿名用户报错,多数不是“没配好”,而是配错了——把 permitAll() 误写成 anonymous(),或者混淆了两者的语义边界。关键不在加不加 Token,而在 Spring Security 如何理解“谁有资格访问”。
anonymous() ≠ 允许所有人访问
这是最常踩的坑。anonymous() 的真实含义是:只允许未认证用户访问,且系统会主动为其创建一个 AnonymousAuthenticationToken(带 ROLE_ANONYMOUS)。一旦请求携带了有效 Token(比如已登录用户的 JWT),SecurityContext 就不再为空,anonymous() 规则直接失效,后续 FilterSecurityInterceptor 仍会按已认证逻辑检查权限——若该用户没被赋予对应角色,就报 403 Access Denied。
- 适用场景:登录页、注册页、验证码接口——这些页面/接口本就不该让已登录用户反复进入
- 错误用法:把 /api/public/data 配成 .anonymous(),结果登录后调用直接 403
- 本质逻辑:它是一道“单向闸机”,只放行空 SecurityContext,拒绝非空
真正开放接口,请用 permitAll()
permitAll() 才是“免检通道”:跳过所有认证与授权过滤器,不查 Token 是否合法,不验角色,不创建 AnonymousAuthenticationToken,也不触发任何 AuthenticationProvider。只要路径匹配,一律放行。
大模型 Token 成本节约工具。在请求到达大模型之前自动压缩 prompt 和上下文,减少 60-95% 的 token 消耗,直接降低 API 成本。支持 Claude/OpenAI/Gemini 等主流模型,提供代理模式、CLI 包装、Python SDK 和 MCP Server 四种接入方式。内置一键安...
- 配置示例:
.antMatchers("/captchaImage", "/swagger-ui/**").permitAll() - 注意顺序:必须放在
.anyRequest().authenticated()之前,否则会被兜底规则覆盖 - 微服务网关层也适用:Spring Cloud Gateway 的
pathMatchers(...).permitAll()同理
AnonymousAuthenticationFilter 的作用别误读
这个过滤器不是为“开放接口”服务的,而是为统一上下文服务的。它在认证链末端运行:如果前面所有 Filter(如 JwtAuthenticationFilter)都没塞入 Authentication,它才补一个 AnonymousAuthenticationToken 到 SecurityContextHolder。
- 目的:避免后续代码(如审计日志、AOP 切面)反复判空
SecurityContextHolder.getContext().getAuthentication() - 副作用:它让
IS_AUTHENTICATED_ANONYMOUSLY表达式可用,但不会帮你绕过权限校验 - 禁用方式(极少需要):
<anonymous enabled="false"></anonymous>或 Java Config 中移除相关 Bean
@Anonymous 注解更安全、更清晰
若依等主流框架封装的 @Anonymous 注解,底层仍是调用 permitAll(),但优势明显:
- 声明式:接口上加个注解,意图一目了然,无需翻 SecurityConfig
- 支持方法级:可精确到某个 POST 方法开放,而非整个 Controller
- 自动扫描:新增接口加注解即生效,不依赖手动维护 antMatchers 列表
- 无歧义:它不叫 @AnonymousOnly,开发者天然理解为“免鉴权”,不会误以为排斥已登录用户

















