我正在开发一个小型图书馆管理系统,用户可以在该系统中登录并添加收藏的书籍。我将Spring Boot与Spring Security、MySql和Hibernate结合使用。用户可以登录,当他们登录时,我可以通过ContexHolder获取他们的信息,我可以将书籍添加到数据库中,获取所有书籍并在前端显示,但现在我想将添加的每本书与当前登录的用户绑定,这样我就只能显示该用户添加的书籍,而不能显示数据库中的所有书籍。我正试着这样做:
My BookController.java:
@RestController
@RequestMapping("/book")
public class BookController {
@Resource
BookDAO bookDao;
@RequestMapping(value = "/save", method = RequestMethod.POST)
public HashMap<String, String> addBook(@RequestBody Book book) {
book.setUser(new Security().getCurrentUser());
bookDao.save(book);
return Response.setSuccess("Book saved successfuly.");
}
我的安全.java:
public class Security {
private UserDAO userDao;
@RequestMapping(value = "/getCurentUser", method = RequestMethod.GET)
public User getCurrentUser() {
return userDao.findByEmail(SecurityContextHolder.getContext().getAuthentication().getName());
}
}
但是,由于某种原因,在这种情况下,方法getCurrentUser返回null,而我得到NullPointerException。但是,当我使用UserController.java中的相同方法时,它会返回我希望返回的内容。这是在同一次运行中测试的(首先我从Securty.java调用了一个方法,它返回null,然后我从UserControll.java调用了方法,我现在登录了user(me))。
这是我的UserController.java(仅getCurrentUser和loginUser方法):
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserDAO userDao;
@Autowired
AuthenticationManager authenticationManager;
@Autowired
BCryptPasswordEncoder encoder;
@RequestMapping(value = "/getCurentUser", method = RequestMethod.GET)
public User getCurrentUser() {
return userDao.findByEmail(SecurityContextHolder.getContext().getAuthentication().getName());
}
...
@RequestMapping(value = "/login", method = {RequestMethod.POST, RequestMethod.GET})
public HashMap<String, String> loginUser(@RequestBody final User user) {
final User foundUser = userDao.findByEmail(user.getEmail());
if (foundUser == null || !encoder.matches(user.getCurentPassword(), foundUser.getCurentPassword())) {
return Response.setError("Bad credentials");
} else {
final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getCurentPassword(), AuthorityUtils.createAuthorityList(foundUser.getRole().name()));
final Authentication authentication = authenticationManager.authenticate(authRequest);
SecurityContextHolder.getContext().setAuthentication(authentication);
return Response.setSuccess(foundUser.getRole().name());
}
}
哦,还有我的书。Java豆:
....
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
....
经过长时间的尝试,我终于解决了这个问题。事实证明,从单独的Security类调用getCurrentUser方法返回了匿名用户,即使拥有ROLE_user的用户已经登录。向UserDAO UserDAO添加@Autowired annots或向整个类添加@Component或@Service annots也没有得到任何结果。呼叫:
userDao.findByEmail(SecurityContextHolder.getContext().getAuthentication().getName())
来自BookController的UserDAO UserDAO-eith@Resource annot也返回了匿名用户。只有当我将@Autowired添加到UserDAO UserDAO时,我才设法获得了当前登录的用户并将该书绑定到他。这是代码:
@RestController
@RequestMapping("/book")
public class BookController {
@Resource
BookDAO bookDao;
@Autowired
UserDAO userDao;
@PreAuthorize("hasRole('ROLE_USER')")
@RequestMapping(value = "/save", method = {RequestMethod.POST, RequestMethod.GET})
public HashMap<String, String> addBook(@RequestBody Book book) {
book.setUser(userDao.findByEmail(SecurityContextHolder.getContext().getAuthentication().getName()));
bookDao.save(book);
return Response.setSuccess("Book saved successfuly.");
}
1-类Security
有@Component
或@Service
注释?
2-userDao
字段为空-您需要使用@Autowired
注入它,以避免getCurrentUser()
方法中的NullPointerException
。