Java Spring用户安全认证
我正在用spring boot开发一个基本的note应用程序。当GET请求到达NoteController时,我想检查用户是否有此便笺。在示例中,id为1的注释属于UserA。如果UserB试图通过以下url:/note/1获取此便笺,我不希望UserB访问此便笺。为了解决这个问题,每次有请求到达NoteController时,我都会从SecurityContextHolder获取经过身份验证的用户,并检查note是否属于该用户。还有比这更好的吗 记事本控制器Java Spring用户安全认证,java,spring,spring-boot,spring-mvc,spring-security,Java,Spring,Spring Boot,Spring Mvc,Spring Security,我正在用spring boot开发一个基本的note应用程序。当GET请求到达NoteController时,我想检查用户是否有此便笺。在示例中,id为1的注释属于UserA。如果UserB试图通过以下url:/note/1获取此便笺,我不希望UserB访问此便笺。为了解决这个问题,每次有请求到达NoteController时,我都会从SecurityContextHolder获取经过身份验证的用户,并检查note是否属于该用户。还有比这更好的吗 记事本控制器 package app.contr
package app.controller;
import app.entity.Note;
import app.entity.User;
import app.service.NoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/note")
public class NoteController
{
@Autowired
private NoteService noteService;
@PostMapping
public Note save(@RequestBody Note note)
{
User user=(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
note.setUser(user);
noteService.save(note);
return note;
}
@PutMapping
public ResponseEntity<Void> update(@RequestBody Note note)
{
User user=(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(noteService.findById(note.getId()).getUser().getId()==user.getId())
{
noteService.update(note);
return new ResponseEntity<>(HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@GetMapping("/{id}")
public ResponseEntity<Note> findById(@PathVariable int id)
{
User user=(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Note note=noteService.findById(id);
if(note.getUser().getId()==user.getId())
return new ResponseEntity<>(note,HttpStatus.OK);
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
@GetMapping
public List<Note> findByUser()
{
User user=(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return noteService.findByUser(user);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteById(@PathVariable int id)
{
User user=(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Note note=noteService.findById(id);
if(note.getUser().getId()==user.getId())
{
noteService.deleteById(id);
return new ResponseEntity<>(HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
}
所有findById()
调用结果都用于授权检查,这意味着可以将逻辑移动到公共位置,即findById()
同样的授权逻辑也可以使用:annotation完成
一个例子如下NoteService.findById(id)
方法可以修改为进行此检查,并且可以删除控制器方法中的用户检查逻辑
@PostAuthorize("returnObject.user.id == principal.id")
public Note findById(Long id)
{
return noteRepository.findById(id);
}
这里,@PostAuthorize
是在内置的returnObject
上完成的
另外,请记住启用GlobalMethodSecurity,如下所示,以使Pre和Post注释正常工作
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
//...
}
希望这有帮助。非常感谢。成功了。在noteController中的其他方法中是否还有其他用途?
@PostAuthorize
注释将替换现有的用户授权代码逻辑。其他什么都不需要做。
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
//...
}