Spring Security 的 AJAX 请求给出 403 Forbidden

Muh*_*edH 5 java ajax spring spring-security spring-boot

我有一个基于spring boot、spring-security、thymeleaf的网站,在某些情况下我也使用ajax。

问题:我在 Spring Security 中使用表单登录安全性。在浏览器中,登录后我可以使用rest API (GET),但是使用Ajax,它会返回http 403错误,即使我的Ajax请求在cookie中包含会话id。

安全配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
    .antMatchers("/admin/**").hasRole("ADMIN")
    .antMatchers("/rest/**").hasRole("ADMIN")
            .anyRequest().permitAll()
     .and()
     .formLogin().loginPage("/sign-in-up")
            .loginProcessingUrl("/signInProcess").usernameParameter("phone").and().logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/");

}
Run Code Online (Sandbox Code Playgroud)

REST API 我测试正确:

@RestController
@RequestMapping("rest/categories")
public class CategoriesRest {
@Autowired
private CategoryService categoryService;

@GetMapping("/")
public ResponseEntity<List<Category>> findAll() {
    List<Category> all = categoryService.getAll();
    if (all.isEmpty()) {
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
    return new ResponseEntity<>(all, HttpStatus.OK);
}

@GetMapping("/{id}")
public ResponseEntity<Category> findById(@PathVariable int id) {
    Category obj = categoryService.get(id);
    if (obj == null) {
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
    return new ResponseEntity<>(obj, HttpStatus.OK);
}

@PostMapping("/")
public ResponseEntity<Category> createMainSlider(@RequestBody Category obj) {
    System.out.println("-------rest Post");

    return new ResponseEntity<>(categoryService.add(obj), HttpStatus.CREATED);
}

@PutMapping("/{id}")
public ResponseEntity<Category> update(@RequestBody Category obj, @PathVariable int id) {
    Category obj1 = categoryService.update(obj);

    System.out.println(obj);
    return new ResponseEntity<>(obj1, HttpStatus.OK);
}

@DeleteMapping("/{id}")
public ResponseEntity<Category> deleteEmp(@PathVariable int id) {
    categoryService.delete(id);
    return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}

}
Run Code Online (Sandbox Code Playgroud)

我的阿贾克斯代码:

$('.deleteBtn').bind('click',function(e){
        e.preventDefault();
        $.ajax({
            type:'DELETE',
            url : "/rest/categories/"+$(e.currentTarget).data('id'),
             xhrFields: {
                  withCredentials: true
               },
             success : function(result) {
                 location.reload();
                 console.log(result);
               },
              error : function(e) {
                alert("Error!")
                console.log("ERROR: ", e);
              }
        })
    })
Run Code Online (Sandbox Code Playgroud)

我的ajax请求头是这样的:

ajax请求头

编辑[GET]请求正常工作,但[PUT,POST,DELETE]不起作用。

Pat*_*mil 9

为什么.csrf().disable().cors()有效?

\n\n

CSRF代表跨站请求伪造

\n\n

简单来说,它是一种随请求发送的令牌,用于防止攻击。为了使用 Spring Security CSRF 保护,我们首先需要确保对任何修改状态的内容使用正确的 HTTP 方法(PATCHPOSTPUTDELETE\xe2\x80\x93 不是GET)。

\n\n

某些框架通过使 user\xe2\x80\x99s 会话无效来处理无效的 CSRF 令牌,但这会导致其自身的问题。相反,默认情况下 Spring Security\xe2\x80\x99s CSRF 保护将产生HTTP 403 accessied

\n\n

Ajax 和 JSON 请求

\n\n

如果您使用 JSON,则无法在 HTTP 参数中提交 CSRF 令牌。相反,您可以在 HTTP 标头中提交令牌。典型的模式是将 CSRF 令牌包含在元标记中

\n\n
<meta name="_csrf" content="${_csrf.token}"/>\n<meta name="_csrf_header" content="${_csrf.headerName}"/>\n\n//jQuery\nvar token = $("meta[name=\'_csrf\']").attr("content");\nvar header = $("meta[name=\'_csrf_header\']").attr("content");\n\n$(document).ajaxSend(function(e, xhr, options) {\n    xhr.setRequestHeader(header, token);\n});\n
Run Code Online (Sandbox Code Playgroud)\n