1. 从403错误认识AccessDeniedException
遇到SpringSecurity的403错误就像在机场被安检拦下——明明带了登机牌(Token),却被拒绝进入候机厅。最近在调试OAuth2登录接口时就踩到这个坑:前端带着有效Token请求/oauth/token接口,明明配置了permitAll,却收到"AccessDeniedException: Access is denied"的红色警告。
这个问题背后藏着SpringSecurity的三重安检机制:
- 配置层:HttpSecurity的antMatchers配置像机场的准入名单
- 决策层:AbstractAccessDecisionManager如同安检主管,协调多个安检员(Voter)投票
- 执行层:WebExpressionVoter等具体实现才是真正检查登机牌的安检员
我曾在项目中配置了这样的白名单:
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.anyRequest().authenticated();
理论上所有访问/oauth/**路径的请求都应该放行,但实际带着Token访问时却触发403。这就像VIP通道写着"所有人可进",但实际却检查邀请函——矛盾的规则导致了系统行为异常。
2. 决策投票器的暗箱操作
2.1 AffirmativeBased的民主投票
当请求触发安全拦截时,AbstractAccessDecisionManager的子类AffirmativeBased会组织投票。它的工作流程就像议会表决:
- 遍历所有Voter实现(议员)
- 收集每个Voter的投票结果(1通过/0弃权/-1拒绝)
- 只要有一个-1


1573

被折叠的 条评论
为什么被折叠?



