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

如何跳过Spring Security中服务间Feign调用的@PreAuthorize校验

如何跳过FeignClient内部调用时的@PreAuthorize校验

场景说明

服务A通过Spring Security配置了方法级权限校验,同时通过FeignClient调用服务B。目前FeignClient接口上标注了@PreAuthorize注解,导致服务A内部调用该Feign方法时会触发权限校验,需要避免这一行为。

服务A的Security配置

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(
        securedEnabled = true,
        jsr250Enabled = true
)
@SecurityScheme(
        name = "bearerAuth",
        type = SecuritySchemeType.HTTP,
        bearerFormat = "JWT",
        scheme = "bearer"
)
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtTokenFilter jwtTokenFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable)
                .sessionManagement(httpSecuritySessionManagementConfigurer ->
                        httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(req -> req
                        .requestMatchers(
                                "/login/**",
                        ).permitAll()
                        .anyRequest().authenticated())
                .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}

FeignClient及调用逻辑

// UserService调用FeignClient
@Service
public class UserService {
    @Autowired
    private SlApiClient slApiClient;

    public CustomerDTO getCustomerById(UUID id) {
        return slApiClient.getCustomerById(id);
    }

    /**
     * 其他使用slApiClient的方法
     */
}
// FeignClient接口
@FeignClient(url = "${endpoints.sl-api-uri}", name = "SL-API-CLIENT-V1", primary = false)
public interface SlApiClient {
    @GetMapping("/users/{id}")
    @PreAuthorize("hasAuthority('users.read')")
    CustomerDTO getCustomerById(@PathVariable UUID id);

    /**
     * 其他方法
     */
}

解决方案

方案1:直接移除FeignClient接口上的@PreAuthorize注解

@PreAuthorize注解的作用是对当前服务(服务A)的方法调用做权限校验,而Feign调用是跨服务请求,权限校验逻辑应该放在服务B的接口上。服务A作为调用方,不需要在Feign接口上添加该注解,直接删除即可跳过校验:

@FeignClient(url = "${endpoints.sl-api-uri}", name = "SL-API-CLIENT-V1", primary = false)
public interface SlApiClient {
    @GetMapping("/users/{id}")
    // 移除@PreAuthorize注解
    CustomerDTO getCustomerById(@PathVariable UUID id);

    /**
     * 其他方法
     */
}

方案2:修改@PreAuthorize表达式放行内部调用

如果需要保留注解(比如有特殊场景),可以修改表达式直接放行该方法的权限校验:

@FeignClient(url = "${endpoints.sl-api-uri}", name = "SL-API-CLIENT-V1", primary = false)
public interface SlApiClient {
    @GetMapping("/users/{id}")
    // 放行该方法的权限校验
    @PreAuthorize("permitAll()")
    CustomerDTO getCustomerById(@PathVariable UUID id);

    /**
     * 其他方法
     */
}

方案3:配置方法级权限的忽略规则

如果有多个Feign接口需要批量处理,可以在SecurityConfig中自定义规则忽略Feign接口的方法校验:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(
        securedEnabled = true,
        jsr250Enabled = true
)
public class SecurityConfig {

    // ... 其他已有配置

    @Bean
    public MethodSecurityMetadataSource methodSecurityMetadataSource() {
        DefaultMethodSecurityMetadataSource metadataSource = new DefaultMethodSecurityMetadataSource();
        // 忽略SlApiClient接口下所有方法的权限校验
        metadataSource.addIgnoredMethods(SlApiClient.class);
        return metadataSource;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 13:17:39