java - 带有 Spring Security 的 AJAX 请求给出 403 Forbidden
问题描述
我有一个基于 spring boot、spring-security、thymeleaf 的网站,在某些情况下我也使用 ajax。
问题:
我在 Spring Security 中使用表单登录安全性。在浏览器中,登录后我可以使用 rest API (GET),但使用ajax它会返回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("/");
}
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);
}
}
- 我的 ajax 代码:
$('.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);
}
})
})
- 我的 ajax 请求标头是这样的: ajax 请求标头
编辑 [GET] 请求工作正常,放 [PUT,POST,DELETE] 不工作。
解决方案
为什么.csrf().disable().cors()
奏效了?
CSRF代表Cross Site Request Forgery
简而言之,它是一种随请求发送以防止攻击的令牌。为了使用 Spring Security CSRF 保护,我们首先需要确保使用正确的 HTTP 方法来处理任何修改状态的内容(PATCH
、POST
、PUT
和DELETE
– not GET
)。
一些框架通过使用户的会话无效来处理无效的 CSRF 令牌,但这会导致其自身的问题。相反,默认情况下 Spring Security 的 CSRF 保护将产生HTTP 403 access denied。
如果您使用的是 JSON,则无法在 HTTP 参数中提交 CSRF 令牌。相反,您可以在 HTTP 标头中提交令牌。一个典型的模式是在元标记中包含 CSRF 令牌
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
//jQuery
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);
});
推荐阅读
- javascript - How to enable Froala editor inside the wrapper div?
- xaml - 如何使用 xamarin.forms 中选择的选项设置主详细信息页面?
- java - “一个组件需要一个类型的 bean”,但是哪一个呢?
- xslt - XSLT - 创建新元素和值
- reactjs - Why my react application not displaying on google chrome browser but it is displayed on chrome ingonito , IE, and other browsers
- python - 在Python中将字符串解码为日文字符
- sql-server - Filtering Gridview with stored procedure in textboxchanged event
- python - Count number of persons in a video
- sql - 使用子字符串从数据库返回值
- algorithm - 给定算法的时间和空间复杂度