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

如何仅在本地主机(localhost)禁用Spring Security的CSRF防护?

没问题,我来帮你搞定这个需求——只给localhost放行CSRF校验,其他域名保持严格验证。下面给你两种实用的实现方式,你可以根据自己的场景选择:

方法一:通过请求来源动态控制CSRF规则

这种方式不需要额外配置文件,直接在Spring Security配置类里根据请求的主机名动态判断是否启用CSRF防护,灵活性更高。

创建或修改你的Security配置类,通过HttpServletRequest获取请求来源,针对性配置CSRF规则:

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRepository;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, HttpServletRequest request) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf
                .csrfTokenRepository(getCsrfTokenRepository(request))
            );
        return http.build();
    }

    private CsrfTokenRepository getCsrfTokenRepository(HttpServletRequest request) {
        String host = request.getServerName();
        // 覆盖常见的本地地址:localhost、127.0.0.1、IPv6本地地址
        boolean isLocalRequest = "localhost".equals(host) 
                || "127.0.0.1".equals(host) 
                || "[::1]".equals(host);
        
        if (isLocalRequest) {
            // 本地请求:返回一个空实现的Repository,相当于禁用CSRF校验
            return new CsrfTokenRepository() {
                @Override
                public CsrfToken generateToken(HttpServletRequest request) {
                    return null;
                }

                @Override
                public void saveToken(CsrfToken token, HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) {}

                @Override
                public CsrfToken loadToken(HttpServletRequest request) {
                    return null;
                }
            };
        } else {
            // 非本地请求:使用你原本的CSRF Token存储方式(这里用Cookie示例)
            return CookieCsrfTokenRepository.withHttpOnlyFalse();
        }
    }
}

注意:如果本地开发用了自定义域名(比如local.test),记得把它也加到isLocalRequest的判断条件里。

方法二:用Spring Profile区分环境(对应你提到的双配置文件方案)

如果你的本地开发和生产环境边界清晰,用Profile来拆分配置会更直观:

  1. 创建两个环境配置文件:

    • application-dev.yml(本地开发环境,对应dev Profile):
      spring:
        security:
          csrf:
            enabled: false
      
    • application-prod.yml(生产环境,对应prod Profile):
      spring:
        security:
          csrf:
            enabled: true
      
  2. 在Security配置类中,为不同Profile配置对应的规则:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.web.SecurityFilterChain;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {
    
        // 生产环境:强制启用CSRF防护
        @Bean
        @Profile("prod")
        public SecurityFilterChain prodSecurityFilterChain(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .csrf(csrf -> csrf.enable());
            return http.build();
        }
    
        // 开发环境:禁用CSRF防护
        @Bean
        @Profile("dev")
        public SecurityFilterChain devSecurityFilterChain(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .csrf(csrf -> csrf.disable());
            return http.build();
        }
    }
    
  3. 启动时激活对应Profile:本地开发用-Dspring.profiles.active=dev,生产环境用-Dspring.profiles.active=prod即可。

小提示:如果应用前端有反向代理(比如Nginx),要确保getServerName()能拿到真实请求的主机名,需要在application.yml里添加server.use-forward-headers=true,避免反向代理覆盖请求来源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:40:02