Это вопрос о безопасности Spring.Весна 3, Весна безопасности. Извлечь аутентифицированный объект пользователя
В моем приложении у меня есть объект пользователя как объект домена. Этот объект содержит реализацию для поддержки объекта Spring UserDetails. Процесс аутентификации (логин/выход) работает нормально.
Проблема в том, что мне нужно извлечь этот объект из сеанса, чтобы принимать решения «бизнес-логики» в моем коде.
Я читал о запросе SecurityContextHolder, но, честно говоря, я до сих пор не знаю, что является лучшим подходом, учитывая, что несколько версий Spring, по-видимому, являются фактором в этих дискуссиях. Кроме того, объект Principal не является для меня решением, поскольку он, похоже, не содержит информации о уровне доступа или роли.
Ниже приведен простой контроллер, иллюстрирующий мою задачу. Он имеет жестко закодированный объект домена пользователя. Мне нужно заменить этот блок кодом, который получит объект User из сеанса Spring Security. Я ищу лучший способ сделать это в течение Весны 3.
- Могу ли я получить этот объект в качестве объекта своего домена или мне нужно получить его как объект Spring UserDetails и его вручную преобразовать?
Может ли этот контекстный поиск безопасности каким-либо образом вводиться в мой контроллер?
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());
Это работает, но я делаю это право? Обратная связь очень ценится. Я все еще не могу получить объект моего домена пользователя из сеанса. Я извлекаю объект UserDetails Spring и создаю объект User моего домена, но в процессе теряется некоторая информация.
java.lang.ClassCastException: org.springframework.security.core.userdetails.User нельзя передать в com.modelsite.domain.User – jacekn
Если я не могу получить объект User в качестве пользователя моего домена, это будет быть немного болью. Из UserDetails я мог бы выяснить, на каком уровне доступа я имею дело, но другой информацией, которая мне нужна, является userId. userName и userId для меня две разные вещи. Если я не могу получить это из сеанса, это будет означать, что мне нужно получить пользователя из базы данных. Что-то, чего я бы хотел избежать. – jacekn
Вы должны настроить Spring Security с помощью функции UserDetailsService, которая возвращает экземпляр вашего пользовательского объекта (пользовательский экземпляр UserDetails), когда пользователь аутентифицируется. Таким образом, он будет доступен непосредственно из «SecurityContextHolder» без создания каких-либо новых промежуточных объектов. Существует больше об использовании 'UserDetailsService' [в справочном руководстве] (http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#tech-userdetailsservice). –