Java Spring用户安全认证

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

我正在用spring boot开发一个基本的note应用程序。当GET请求到达NoteController时,我想检查用户是否有此便笺。在示例中,id为1的注释属于UserA。如果UserB试图通过以下url:/note/1获取此便笺,我不希望UserB访问此便笺。为了解决这个问题,每次有请求到达NoteController时,我都会从SecurityContextHolder获取经过身份验证的用户,并检查note是否属于该用户。还有比这更好的吗

记事本控制器

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 {
//...
}