Spring получает пользовательские пользовательские данные в SecurityContextHolder

#java #spring #security

#java #spring #Безопасность

Вопрос:

Я использую SpringSecurity в своем веб-проекте. У меня есть объект User, который сохранен в БД. Мне нужно выполнять запросы в BD с идентификатором пользователя, чтобы получить любую информацию из других таблиц в этом BD. Как я могу получить своего пользователя из SecurityContextHolder вместо стандартного пользователя Spring (у этого пользователя нет идентификатора) после аутентификации в Spring Security?

  @Entity
@Table(name = "users")
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "login")
    private String login;

    @Column(name = "password")
    private String password;

    getters and setters
  

PS. Извините за мой английский 🙂

Ответ №1:

Вы должны реализовать интерфейс UserDetailsService и интерфейс UserDetails в другом классе. Например:

CustomUserDetailsService:

 @Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
    // your UserRepository for your user
    private final UserRepository userRepository;

    @Autowired
    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (null == user || ! user.getUsername().equals(username)) {
            throw new UsernameNotFoundException("No user present with username: "   username);
        } else {

            return new CustomUserDetails(user);
        }
    }
}
  

Пользовательские пользовательские данные:

 // You want to extend your User class here
public class CustomUserDetails extends User implements UserDetails {
    private static final long serialVersionUID = 1L;
    private Users user;

    public CustomUserDetails(User user) {
        super(user);
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // You don't talk about UserRoles, so return ADMIN for everybody or implement roles. 
        return AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN");
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        // just for example
        return this.user.getActive() == true;
    }

    @Override
    public String getUsername() {
        return this.user.getUsername();
    }

    @Override
    public String getPassword() {
        return this.user.getPassword();
    }

    // Just an example to put some addititional Data to your logged in user

    public String getUserDatabase() {
        return "usertable"   Integer.toString(1   this.user.getUserId());
    }


}
  

В вашем User классе создайте пустой конструктор для гибернации и тот, который принимает экземпляр пользователя:

 @Entity
@Table(name = "users")
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "login")
    private String login;

    @Column(name = "password")
    private String password;

    public User() {}

    public User(User user) {
        this.id = user.getId();
        this.name = user.getName();
        // … the same for all properties.
    }
}
  

В вашем WebSecurityConfig @Autowire CustomUserDetailsService и введите его в поток аутентификации:

 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final
    UserDetailsService service;

    @Autowired
    public WebSecurityConfig(UserDetailsService service) {
        this.service = service;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(service).passwordEncoder(passwordEncoder());

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //left out because not related here
    }
}
  

И это все. Теперь вы можете передать аутентифицированного участника своим пользовательским пользовательским данным в каждом контроллере или у поставщика с:

 CustomUserDetails userDetails = 
    (CustomUserDetails) SecurityContextHolder
        .getContext()
        .getAuthentication()
        .getPrincipal();
  

Комментарии:

1. Что такое «private final UserRepository UserRepository»?

2. Это ваш пользовательский репозиторий, интерфейс, с помощью которого вы получаете запрос к своей базе данных

3. Пожалуйста, посмотрите на мои классы.