Spring boot Spring REST secure仅删除拥有的(仅由应用程序最终用户创建的)资源
我试图找到如何安全(仅由所有者)删除REST资源的最佳解决方案 目标: 该资源只能由该资源的所有者/创建者(指其创建该资源的所有者/创建者)删除。 前提:Spring boot Spring REST secure仅删除拥有的(仅由应用程序最终用户创建的)资源,spring-boot,rest,spring-security,Spring Boot,Rest,Spring Security,我试图找到如何安全(仅由所有者)删除REST资源的最佳解决方案 目标: 该资源只能由该资源的所有者/创建者(指其创建该资源的所有者/创建者)删除。 前提: 每次应用程序最终用户创建客户端帐户时,他都会收到一个JWT令牌 为了能够访问REST资源,客户端应该提供有效的JWT 通过客户过滤器对每个来电进行JWT验证: @组件公共类JwtRequestFilter扩展OncePerRequestFilter{ @Autowired private ClientAuthService c
@Autowired
private ClientAuthService clientAuthService;
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeaderDate = request.getHeader("Date");
if (authorizationHeaderDate != null){
if (DateTimeUtil.isLaterInMinThenNow(
LocalDateTime.parse(authorizationHeaderDate,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), 2)) {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.clientAuthService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
= new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
}
}
chain.doFilter(request, response);
}
}
@DeleteMapping("/clients/{id}")
public ResponseEntity<Client> deleteClientById(@PathVariable(required = true) Long id){
return ResponseEntity.ok(clientService.deleteClientById(id));
}
@DeleteMapping(“/clients/{id}”)
public ResponseEntity deleteClientById(@PathVariable(required=true)长id){
返回ResponseEntity.ok(clientService.deleteClientById(id));
}
问题是:如何防止此类安全问题?您想使用Spring基于表达式的访问控制: 您可以对REST端点方法或服务方法进行注释,并使用EL表达式对用户进行授权。以下是Spring文档中的一个示例,您可以进行调整:
@PreAuthorize("#n == authentication.name")
Contact findContactByName(@Param("n") String name);
现在-您没有要求,但是您应该考虑遵守HTTP谓词,它使用与您的动作相匹配的HTTP谓词(即对于删除资源的请求使用删除HTTP动作):
不要使用使用GET HTTP方法删除资源的REST服务-对于任何了解REST的人来说,这是没有意义的:
@GetMapping(“/clients/{id}”)
应该是
@DeleteMapping(“/clients/{id}”)
要使用Spring基于表达式的访问控制:
您可以对REST端点方法或服务方法进行注释,并使用EL表达式对用户进行授权。以下是Spring文档中的一个示例,您可以进行调整:
@PreAuthorize("#n == authentication.name")
Contact findContactByName(@Param("n") String name);
现在-您没有要求,但是您应该考虑遵守HTTP谓词,它使用与您的动作相匹配的HTTP谓词(即对于删除资源的请求使用删除HTTP动作):
不要使用使用GET HTTP方法删除资源的REST服务-对于任何了解REST的人来说,这是没有意义的:
@GetMapping(“/clients/{id}”)
应该是
@DeleteMapping(“/clients/{id}”)
关于使用HTTP DELETE动词,您是完全正确的,对于阅读本主题的人来说。我建议将“您应该考虑”翻译为“强制性”(即使是spring、REST理论,也不要施加如此严格的限制)使用这些动词。我的错误只是一个愚蠢的复制/粘贴,我已经做了,但我还没有纠正。重新考虑这个问题,我会调查,并最终用一个例子来完成这个主题。非常感谢。事实上,情况是这样的:我会尝试看看是否有效,关于使用HTTP删除动词,你是完全正确的一读到这个话题,我建议把“你应该考虑”翻译成“强制性”(即使是弹簧、休息理论,也不要强加这样严格的限制)使用这些动词。我的错误只是一个愚蠢的复制/粘贴我已经做了,我还没有纠正。重新考虑这个问题,我会调查,并最终用一个例子来完成这个主题。非常感谢。事实上,情况是这样的:我会试着看看它是否也起作用