请求 springboot 后台接口,返回 Failed to load resource: the server responded with a status of 403

我在 springboot 项目中定义好了一个接口,想通过前端 ajax 异步请求该接口,来获取相关数据,发现并没有进入该接口的断点,于是查看前端控制台信息,发现如下错误:

Failed to load resource: the server responded with a status of 403 ()

Note: 我在 springboot 中配置了 security,另外我用的模板引擎是 Thymeleaf, 前端框架 jquery,代码如下:

@EnableWebSecurity
@EnableGlobalMethodSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    /**
     * http 权限控制
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 资源访问控制
        http.authorizeRequests()
                .antMatchers("/user/login").permitAll()
                .antMatchers("/home/**").permitAll()
                .antMatchers("/tag/**").permitAll()
//                .antMatchers("/question/**").permitAll()
//                .antMatchers("/static/**").permitAll()
                .antMatchers(HttpMethod.POST, "/question").hasRole("USER")
                .antMatchers(HttpMethod.PUT, "/question").hasRole("USER")
                .and()
                .formLogin()
                .loginPage("/user/login") // 配置角色登录处理入口
                .loginProcessingUrl("/login")
                .defaultSuccessUrl("/home") // 设置默认登录后 forword url
                .and();
    }

    /**
     * 自定义认证策略
     * @param auth
     * @throws Exception
     */
    @Autowired
    public void globalConfigure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider()).eraseCredentials(true);
    }

    @Bean
    public AuthProvider authProvider() {
        return new AuthProvider();
    }
}

1 个解决方案

AllenJiang
中间件研发,关注微信公众号 : 小哈学Java, 回复"666", 即可免费领取10G学习&面试资料

原因是 spring security 默认是开启了 CSRF(跨站请求伪造) 的防护的,你可以在 configure 方法中添加代码,禁用掉这个功能,但是不推荐这么做

http.csrf().disable();

正确的做法是:

  • 1.在相关 Thymeleaf html 文件 header 头中定义相关参数:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"><head>
<meta name="_csrf" th:content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
  • 2.js 代码:
var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(header, token);
    });

$.ajax({
url: url,
method: 'DELETE',
success: function(result) {
    $('#table').bootstrapTable('remove', {
        field: 'id',
        values: [row.id]
    });
},
    error:function(result) {
    console.log(result);
}
});

你还可以参考 stackoverflow 这个回答