Spring Security + MongoDB, просьба постоянно получать 401 - PullRequest
0 голосов
/ 01 ноября 2018

Я изучаю, как использовать Spring и как реализовать Spring Security в моем проекте, используя Roles и MongoDB.

У меня есть модель User со списком ролей, и я хочу разрешить только пользователю ADMIN использовать некоторые конечные точки из контроллера.

Вот класс пользователя и перечисление роли:

 @Document(collection = "Users")
public class User {
    @Id
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private String password;
    private List<Role> roles;

    //constructor + getters and setters
}

public enum Role {
    ADMIN,
    BASIC_USER
}

Я использую эту реализацию UserDetails: я думаю, что здесь проблема ...

public class CustomUserDetails implements UserDetails {
    private User user;

    public CustomUserDetails() {
    }

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

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.user.getRoles().stream().map(role -> new SimpleGrantedAuthority(String.format("ROLE_%s", role))).collect(Collectors.toList());

    }

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

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

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

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

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

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

    public User getUser() {
        return user;
    }

}

UserDetailsService выглядит так:

public class CustomUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        final User user = userRepository.findByEmail(email);

        if (Objects.isNull(user)) {
            throw new UsernameNotFoundException("User not found");
        }

        return new CustomUserDetails(user);
    }
}

Я сделал эту конфигурацию:

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(createUserDetailsService()).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/users/**").permitAll()
                .antMatchers( "/users/**").authenticated().anyRequest().hasAnyRole("ADMIN")
                .antMatchers("/users/me").authenticated().anyRequest().hasAnyRole("ADMIN", "BASIC_USER")
                .antMatchers( "/users/**").permitAll()
                .and()
                .formLogin().disable()
                .httpBasic();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        /* To allow Pre-flight [OPTIONS] request from browser */
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }

    /**
     * Create password encoder bean used for encrypting the password
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * Create user service bean used for find the user by email
     * @return
     */
    @Bean
    public UserDetailsService createUserDetailsService() {
        return new CustomUserDetailsServiceImpl();
    }
}

Когда я делаю любой вызов с Почтальоном на localhost: 8080 / пользователи, использующие базовую аутентификацию с данными администратора из БД, все время получают 401 Unauthorized Статус

Мне кажется, проблема в том, что я использую Enum для ролей, и я не знаю, как правильно построить реализацию UserDetails.

Если поможет, это UserController

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping(path = "")
    public List<User> getUsers(){
        return this.userService.getUsers();
    }

}

Когда я использовал MySQL для этого проекта (с теми же классами для безопасности), приложения работали отлично. В этой реализации я использовал таблицы Roles, Users и Users_Roles.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...