Spring защита получить объект пользователя

Я реализовал аутентификацию пользователя через Spring Security Framework, и все работает нормально. Я могу войти в систему и выйти из системы, я могу получить имя зарегистрированного пользователя, например:

String userName = ((UserDetails) auth.getPrincipal()).getUsername();

Теперь я хочу получить пользователя как объект из базы данных (мне нужен идентификатор пользователя и другие пользовательские свойства).

Как я уже пробовал:

User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

После этого я получил следующее исключение:

Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to net.viralpatel.contact.model.User

Вот вопрос: как я могу получить User как объект, как мне изменить мои классы UserDetailsServiceImpl и UserAssembler, любые идеи?

@Component
@Transactional
public class UserDetailsServiceImpl implements UserDetailsService{

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private UserAssembler userAssembler;

    private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);

    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        User user = userDAO.findByEmail(username);

        if(null == user) throw new UsernameNotFoundException("User not found");
        return userAssembler.buildUserFromUser(user);
    }
}

И еще один:

@Service("assembler")
public class UserAssembler {

    @Autowired
    private UserDAO userDAO;

    @Transactional(readOnly = true)
    public User buildUserFromUser(net.viralpatel.contact.model.User user) {
        String role = "ROLE_USER";//userEntityDAO.getRoleFromUserEntity(userEntity);

        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(new GrantedAuthorityImpl(role));

        return new User(user.getLogin(), user.getPassword(), true, true, true, true,  authorities);
    }
}

Ответ 1

По существу, вам нужно вернуть реализацию UserDetails, которая обеспечивает доступ к вашему User.

У вас есть два варианта:

  • Добавьте свой User в качестве поля (вы можете расширить его org.springframework.security.core.userdetails.User):

    public class UserPrincipal extends org.springframework.security.core.userdetails.User {
        private final User user;
       ...
    }  
    

    и получим a User из этого поля:

    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    User user = ((UserPrincipal) principal).getUser();
    
  • Создайте класс, который расширяет ваш User и реализует UserDetails:

    public class UserPrincipal extends User implements UserDetails {
        ...
        public UserPrincipal(User user) {
            // copy fields from user
        }
    }
    

    Этот подход позволяет напрямую передать принципалу в User:

    User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    

Ответ 2

Похоже, ваш класс User не расширяет Spring org.springframework.security.core.userdetails.User класс.

Вот пример кода для ссылки, я назвал класс с именем "AuthenticUser":

 public class AuthenticUser extends User {

        public AuthenticUser(String username, String password, boolean enabled,
        boolean accountNonExpired, boolean credentialsNonExpired,
        boolean accountNonLocked,
        Collection<? extends GrantedAuthority> authorities) {

        super(username, password, enabled, accountNonExpired, credentialsNonExpired,
            accountNonLocked, authorities);
    }
   .....
   .....
 }

Теперь вы можете создать объект этого класса в своем коде и установить его как часть Spring Контекст аутентификации, например

  AuthenticUser user  = new AuthenticUser(username, password, .... rest of the parameters);
  Authentication authentication =  new UsernamePasswordAuthenticationToken(user, null,
      user.getAuthorities());
  SecurityContextHolder.getContext().setAuthentication(authentication);

Это приведет к аутентификации вашего пользователя и настройке пользователя в контексте безопасности.

Ответ 3

Вам необходимо реализовать свой собственный UserDetailsService и свой собственный объект UserDetails (согласно вашему желанию):

public class CustomService implements UserDetailsService {
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String userId) {

    Account account = accountDAO.findAccountByName(userId);

    // validation of the account
    if (account == null) {
        throw new UsernameNotFoundException("not found");
    }
    return buildUserFromAccount(account);
}


@SuppressWarnings("unchecked")
@Transactional(readOnly = true)
private User buildUserFromAccount(Account account) {

    // take whatever info you need
    String username = account.getUsername();
    String password = account.getPassword();
    boolean enabled = account.getEnabled();
    boolean accountNonExpired = account.getAccountNonExpired();
    boolean credentialsNonExpired = account.getCredentialsNonExpired();
    boolean accountNonLocked = account.getAccountNonLocked();

    // additional information goes here
    String companyName = companyDAO.getCompanyName(account);


    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    for (Role role : account.getRoles()) {
        authorities.add(new SimpleGrantedAuthority(role.getName()));
    }

    CustomUserDetails user = new CustomUserDetails (username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,
            authorities, company);

    return user;
}


public class CustomUserDetails extends User{

// ...
public CustomUserDetails(..., String company){
     super(...);
     this.company = company;
}

private String company;

public String getCompany() { return company;}

public void setCompany(String company) { this.company = company;}
}

Примечание:
Это стандартная реализация класса User, в которой у вас есть какая-то пользовательская информация, которую вы можете создать пользовательский класс и расширить класс User