Spring Security 教程(21)、默认的访问决策管理器

三种投票策略

vote-decision-manager 配图
vote-decision-manager 配图
vote-decision-manager 配图

Spring Security 的 AccessDecisionManager 通过 AccessDecisionVoter 的投票来决定是否允许访问。有三种投票策略:

AffirmativeBased(默认)

只要有一个Voter 投票允许,就通过。

1
2
3
4
Voter 1: DENY
Voter 2: AFFIRMATIVE
Voter 3: ABSTAIN
结果:允许访问

适合大多数场景,只要有一个来源授权就放行。

ConsensusBased

大多数 Voter 投票允许,才通过。如果平票,根据 allowIfEqualGrantedDeniedDecisions 决定。

1
2
3
4
Voter 1: DENY
Voter 2: AFFIRMATIVE
Voter 3: ABSTAIN
结果:取决于 allowIfEqualGrantedDeniedDecisions

适合需要共识的场景,比如需要多个部门审批的操作。

UnanimousBased

所有 Voter 都必须投票允许,才通过。任何一个 Voter 投 DENY 就拒绝。

1
2
3
4
Voter 1: AFFIRMATIVE
Voter 2: AFFIRMATIVE
Voter 3: DENY
结果:拒绝访问

适合最严格的场景,任何一票否决都生效。

自定义 AccessDecisionManager

1
2
3
4
5
6
7
8
9
@Bean
public AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = Arrays.asList(
new WebExpressionVoter(),
new RoleVoter(),
new AuthenticatedVoter()
);
return new AffirmativeBased(decisionVoters);
}

自定义 Voter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Component
public class CustomAccessDecisionVoter implements AccessDecisionVoter<Object> {

@Override
public boolean supports(ConfigAttribute attribute) {
return "CUSTOM_PERMISSION".equals(attribute.getAttribute());
}

@Override
public boolean supports(Class<?> clazz) {
return true;
}

@Override
public int vote(Authentication authentication, Object object,
Collection<ConfigAttribute> attributes) {
// 自定义投票逻辑
if (hasCustomPermission(authentication)) {
return ACCESS_GRANTED;
}
return ACCESS_DENIED;
}
}

选择策略的建议

场景 推荐策略
普通 Web 应用 AffirmativeBased(默认)
需要多因素授权 ConsensusBased
高安全要求(金融、政府) UnanimousBased
混合场景 自定义 AccessDecisionManager