2012-01-06 4 views
4

Это вопрос о безопасности Spring.Весна 3, Весна безопасности. Извлечь аутентифицированный объект пользователя

В моем приложении у меня есть объект пользователя как объект домена. Этот объект содержит реализацию для поддержки объекта Spring UserDetails. Процесс аутентификации (логин/выход) работает нормально.

Проблема в том, что мне нужно извлечь этот объект из сеанса, чтобы принимать решения «бизнес-логики» в моем коде.

Я читал о запросе SecurityContextHolder, но, честно говоря, я до сих пор не знаю, что является лучшим подходом, учитывая, что несколько версий Spring, по-видимому, являются фактором в этих дискуссиях. Кроме того, объект Principal не является для меня решением, поскольку он, похоже, не содержит информации о уровне доступа или роли.

Ниже приведен простой контроллер, иллюстрирующий мою задачу. Он имеет жестко закодированный объект домена пользователя. Мне нужно заменить этот блок кодом, который получит объект User из сеанса Spring Security. Я ищу лучший способ сделать это в течение Весны 3.

  1. Могу ли я получить этот объект в качестве объекта своего домена или мне нужно получить его как объект Spring UserDetails и его вручную преобразовать?
  2. Может ли этот контекстный поиск безопасности каким-либо образом вводиться в мой контроллер?

    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 моего домена, но в процессе теряется некоторая информация.

ответ

8

Обычно основной объект, содержащийся в успешном Authentication, будет экземпляром вашего пользовательского объекта. Таким образом, для быстрого решения, используйте

Authentication a = SecurityContextHolder.getContext().getAuthentication(); 
User currentUser = (User)a.getPrincipal(); 

, но и (как только вы получите, что работает), вы можете захотеть взглянуть на ответ, который я только что дал (на подобный вопрос) о том, как inject a custom security context accessor.

+0

java.lang.ClassCastException: org.springframework.security.core.userdetails.User нельзя передать в com.modelsite.domain.User – jacekn

+0

Если я не могу получить объект User в качестве пользователя моего домена, это будет быть немного болью. Из UserDetails я мог бы выяснить, на каком уровне доступа я имею дело, но другой информацией, которая мне нужна, является userId. userName и userId для меня две разные вещи. Если я не могу получить это из сеанса, это будет означать, что мне нужно получить пользователя из базы данных. Что-то, чего я бы хотел избежать. – jacekn

+0

Вы должны настроить Spring Security с помощью функции UserDetailsService, которая возвращает экземпляр вашего пользовательского объекта (пользовательский экземпляр UserDetails), когда пользователь аутентифицируется. Таким образом, он будет доступен непосредственно из «SecurityContextHolder» без создания каких-либо новых промежуточных объектов. Существует больше об использовании 'UserDetailsService' [в справочном руководстве] (http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#tech-userdetailsservice). –

Смежные вопросы