这是一个Spring Security问题。
在我的应用程序中,我有一个User实体作为域对象。该对象包含支持Spring UserDetails对象的实现。身份验证(登录/注销)过程正常。
挑战在于我需要从会话中提取该对象,以便在我的代码中做出“业务逻辑”决策。
我一直在阅读有关查询SecurityContextHolder的内容,但坦率地说,我仍然不知道什么是最好的方法,因为多个Spring版本似乎是这些讨论中的一个因素。此外,Principal对象不适合我,因为它似乎不包含任何访问级别或角色信息。
下面是一个简单的控制器来说明我的挑战。它的用户域对象是硬编码的。我需要用将从Spring Security会话获取User对象的代码替换该块。我正在寻找在Spring 3中做到这一点的最好方法。
可以以某种方式将此安全上下文查找注入我的控制器吗?
public class HomeController {
@RequestMapping(value="/home.html", method=RequestMethod.GET)
public ModelAndView getHomePage(Map<String, Object> model) {
// Get current user
User currentUser=new User();
currentUser.setUserName("Admin");
currentUser.setAccessLevel(UserAccessLevel.ADMINISTRATOR);
// Construct HomePage bean
HomeBean bean=new HomeBean();
bean.setCurrentUserName(currentUser.getUserName());
// Construct list of catalogs
Collection<String> catalogList=new ArrayList<String>();
catalogList.add("articles");
catalogList.add("files");
catalogList.add("comments");
if(currentUser.hasAdministratorAccessLevel()) {
catalogList.add("users");
}
bean.setCatalogList(catalogList);
// Construct and return ModelAndView
ModelAndView mav=new ModelAndView();
mav.setViewName(WebView.HOME_PAGE.getViewName());
mav.addObject(bean.getBeanId(), bean);
return mav;
}
===更新2012-01-07 ====================================== ================
我正在处理卢克的建议。从会话中获取UserDetails并将其转换为返回的我的域User对象的方法在我的UserService中。
这是我的控制器:
@Controller
public class HomeController {
@Autowired
private UserService userService;
@RequestMapping(value="/home.html", method=RequestMethod.GET)
public ModelAndView getHomePage(Map<String, Object> model) {
// Construct HomePage bean
HomeBean bean=new HomeBean();
User currentUser=userService.getCurrentlyAuthenticatedUser();
bean.setCurrentUserName(currentUser.getUserName());
这是UserServiceImpl.getCurrentlyAuthenticatedUser()的关键代码:
@Override
public User getCurrentlyAuthenticatedUser() {
User currentUser=new User();
Authentication a = SecurityContextHolder.getContext().getAuthentication();
UserDetails currentUserDetails = (UserDetails) a.getPrincipal();
if(currentUserDetails==null) {
return currentUser;
}
currentUser.setUserName(currentUserDetails.getUsername());
这样可行,但我这样做了吗?反馈非常感谢。我仍然无法从会话中检索我的用户域对象。我正在检索Spring的UserDetails对象,并使用它构建我的域User对象,但在此过程中一些信息丢失。
答案 0 :(得分:8)
通常,成功Authentication
中包含的主要对象将是您的用户对象的实例。因此,要快速解决方案,请使用
Authentication a = SecurityContextHolder.getContext().getAuthentication();
User currentUser = (User)a.getPrincipal();
但是(一旦你开始工作),你可能想看看我刚才给出的答案(关于如何inject a custom security context accessor的类似问题。
答案 1 :(得分:0)
Spring还提供了一个@AuthenticationPrincipal批注,它用于解析Authentication.getPrincipal()。可以像下面这样使用...
public ResponseEntity<UserProfileResponse>UserProfile(@AuthenticationPrincipal JwtAuthenticationToken principal){