You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Security 4.0.4中实现可获取URL路径变量的AccessDecisionVoter

Spring Security 4.0.4 版本未内置 4.2 版本新增的路径变量权限表达式原生支持,你找到的 3.1 版本基于 AccessDecisionVoter 的实现方案完全兼容 4.0.4 版本,也是该版本下的最优实现方案,具体实现步骤如下:

实现逻辑说明

Spring Security 中AccessDecisionVoter的vote方法入参的实际类型为FilterInvocation,可从中拿到当前请求的完整路径,再通过 Spring 自带的UriTemplate工具即可解析出路径变量,后续执行自定义权限校验逻辑即可。

代码实现

1. 自定义路径变量感知的投票器

import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.web.util.UriTemplate;
import java.util.Collection;
import java.util.Map;

public class PathVariableAccessVoter implements AccessDecisionVoter<FilterInvocation> {
    // 自定义权限标识前缀,按需调整
    private static final String PERMISSION_PREFIX = "PERM_RESOURCE_";

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return attribute.getAttribute() != null && attribute.getAttribute().startsWith(PERMISSION_PREFIX);
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

    @Override
    public int vote(Authentication authentication, FilterInvocation filterInvocation, Collection<ConfigAttribute> attributes) {
        // 匹配路径获取变量,示例路径为 /resource/{resourceId},按需替换为你的业务路径
        UriTemplate uriTemplate = new UriTemplate("/resource/{resourceId}");
        Map<String, String> pathVariables = uriTemplate.match(filterInvocation.getRequestUrl());
        String resourceId = pathVariables.get("resourceId");
        
        // 自定义权限校验逻辑,比如校验当前用户是否有该资源的访问权限
        if (hasPermission(authentication, resourceId)) {
            return ACCESS_GRANTED;
        }
        return ACCESS_DENIED;
    }

    private boolean hasPermission(Authentication authentication, String resourceId) {
        // 此处替换为你的业务权限校验逻辑
        return true;
    }
}

2. 配置投票器到权限决策管理器

XML 配置方式
<security:http access-decision-manager="customAccessDecisionManager">
    <!-- 其他HTTP配置 -->
    <security:intercept-url pattern="/resource/**" access="PERM_RESOURCE_ACCESS"/>
</security:http>

<bean id="customAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <constructor-arg>
        <list>
            <!-- 注入自定义投票器 -->
            <bean class="com.yourpackage.PathVariableAccessVoter"/>
            <!-- 保留默认投票器 -->
            <bean class="org.springframework.security.access.vote.RoleVoter"/>
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
        </list>
    </constructor-arg>
</bean>
JavaConfig 配置方式
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/resource/**").access("PERM_RESOURCE_ACCESS")
                .anyRequest().authenticated()
                .and()
            .accessDecisionManager(accessDecisionManager());
    }

    @Bean
    public AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter<?>> voterList = new ArrayList<>();
        voterList.add(new PathVariableAccessVoter());
        voterList.add(new RoleVoter());
        voterList.add(new AuthenticatedVoter());
        return new AffirmativeBased(voterList);
    }
}

多路径适配优化

如果需要支持多个不同的路径规则,可在自定义投票器中维护一个UriTemplate列表,遍历匹配当前请求路径,拿到对应路径变量后再执行校验即可。

内容的提问来源于stack exchange,提问作者Delsh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 04:18:01