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

如何从AngularJS控制器提交含CSRF Token的数据至REST控制器

解决AngularJS + Spring Security CSRF启用后POST/PUT 405问题

首先,咱们先理清问题根源:启用CSRF防护后,Spring Security要求所有**修改类请求(POST/PUT/DELETE)**必须携带CSRF Token,同时你的跨域(CORS)配置和AngularJS的请求处理没有跟上这个要求,导致浏览器预检请求(OPTIONS)处理失败,最终触发405错误。下面一步步给你解决:


第一步:调整Spring端的CORS与CSRF配置

1. 修复CORS过滤器(处理OPTIONS请求与跨域头)

你的CORSFilter需要做三个关键修改:允许携带Cookie、放行CSRF相关请求头、正确处理OPTIONS预检请求(浏览器会先发这个请求确认跨域权限):

public class CORSFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        
        // 不要用*,带Cookie的跨域请求必须指定具体源,这里动态获取请求的Origin
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        // 新增X-XSRF-TOKEN到允许的请求头列表
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type, X-XSRF-TOKEN");
        // 允许携带Cookie(必须开启,否则前端拿不到CSRF Token的Cookie)
        response.setHeader("Access-Control-Allow-Credentials", "true");

        // 直接响应OPTIONS请求,不用走后续过滤器链
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }
    public void init(FilterConfig filterConfig) {}
    public void destroy() {}
}

2. 配置Spring Security的CSRF Token存储

默认Spring Security会把CSRF Token存在XSRF-TOKEN Cookie里,但默认是HttpOnly=true(前端JS读不到),所以要修改配置让前端能读取这个Cookie:
在SecurityConfiguration的configure(HttpSecurity http)方法里,更新CSRF部分:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/restUser/**").access("hasRole('ADMIN')")
            .and().formLogin()
            .loginPage("/login").loginProcessingUrl("/login")
            .usernameParameter("usernameId").passwordParameter("password")
            .and().rememberMe().rememberMeParameter("remember-me")
            .tokenRepository(tokenRepository).tokenValiditySeconds(86400)
            .and().csrf()
                // 配置CSRF Token Cookie允许前端JS读取
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and().exceptionHandling().accessDeniedPage("/Access_Denied");
}

第二步:AngularJS端配置自动携带CSRF Token

AngularJS其实默认自带CSRF Token自动处理逻辑,但需要确保几个配置正确:
在你的AngularJS模块的config里添加以下配置:

angular.module('yourAppName', [])
.config(['$httpProvider', function($httpProvider) {
    // 告诉AngularJS从哪个Cookie读CSRF Token(和Spring配置的一致)
    $httpProvider.defaults.xsrfCookieName = 'XSRF-TOKEN';
    // 告诉AngularJS把Token放到哪个请求头里(和Spring期望的一致)
    $httpProvider.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';
    // 开启携带Cookie,这样CSRF Token的Cookie才会被发送到后端
    $httpProvider.defaults.withCredentials = true;
}]);

控制器里正常提交请求即可

配置好后,你在控制器里用$http.post/$http.put的时候,AngularJS会自动帮你把CSRF Token放到请求头里,不需要手动处理:

angular.module('yourAppName')
.controller('UserController', ['$http', function($http) {
    // 创建用户示例
    this.createUser = function(userData) {
        $http.post('/restUser', userData)
        .then(function(res) {
            console.log('用户创建成功!');
        }, function(err) {
            console.error('创建失败:', err);
        });
    };

    // 更新用户示例
    this.updateUser = function(userId, userData) {
        $http.put(`/restUser/${userId}`, userData)
        .then(function(res) {
            console.log('用户更新成功!');
        }, function(err) {
            console.error('更新失败:', err);
        });
    };
}]);

为什么之前会报405?

  1. 启用CSRF后,浏览器会先发OPTIONS预检请求,你的旧CORS过滤器没有直接响应OPTIONS,导致请求走到Spring Security的过滤器链,触发权限拦截。
  2. 跨域配置没有允许携带Cookie和CSRF相关请求头,AngularJS无法读取和发送CSRF Token,后端验证失败后返回405。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:42:45