Spring security продолжает возвращать 401 несанкционированный код, несмотря на предоставленные правильные учетные данные - PullRequest
1 голос
/ 21 февраля 2020

После настройки пользовательской службы сведений о пользователе, которая использует встроенную базу данных H2 для получения учетных данных пользователя, я продолжаю получать 401 несанкционированных ошибок при выполнении команды post, даже если имя пользователя и пароль доступны. Я не знаю, имеет ли это какое-то значение, но консоль все еще печатает сгенерированный пароль безопасности (хотя автоматически сгенерированные учетные данные возвращают ту же ошибку 401). Пожалуйста, взгляните на мой код ниже и сообщите мне любые предложения или исправления, доступные.

Модель пользователя ...

@Entity
public class ApplicationUser {
    @Id
    private Long id;

    private String username, password, role;

    public ApplicationUser(String username, String role, String password) {
        this.username=username;
        this.password=password;
        this.role=role;
    }

    public ApplicationUser() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    @Override
    public String toString() {
        return "ApplicationUser{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", role='" + role + '\'' +
                '}';
    }
}

Класс хранилища пользователя ...

@Repository
public class AppUserRepository {
    @Autowired
    JdbcTemplate jdbcTemplate;

    static class ApplicationUserRowMapper implements RowMapper<ApplicationUser> {
        @Override
        public ApplicationUser mapRow(ResultSet rs, int rowNum) throws SQLException {
            ApplicationUser applicationUser = new ApplicationUser();
            applicationUser.setUsername(rs.getString("username"));
            applicationUser.setPassword(rs.getString("password"));
            applicationUser.setRole(rs.getString("userrole"));
            return applicationUser;
        }
    }

    public List<ApplicationUser> findAll() {
        return jdbcTemplate.query("select u.username, u.password, ur.userrole from ApplicationUsers u, ApplicationUsers_Role ur where u.username = ur.username",
                new ApplicationUserRowMapper());
    }

    public ApplicationUser findByUsername(String username) {
        return jdbcTemplate.queryForObject("select u.username, u.password, ur.userrole from ApplicationUsers u, ApplicationUsers_Role ur where u.username = ? and u.username = ur.username",
                new Object[] {username}, new ApplicationUserRowMapper());
    }
}

Класс конфигурации безопасности ...

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "security_package")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomUserDetailsService customUserDetailsService;

    @Autowired
    CustomAuthenticationProvider customAuthenticationProvider;

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

    @Autowired
    public void configureGlobal (AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider);
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().antMatchers("/login").permitAll().anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password");
    }
}

Пользовательский провайдер аутентификации ...

@Service
public class CustomAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    AppUserRepository userRepository;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String name = authentication.getName();
        String password = authentication.getCredentials().toString();

        ApplicationUser user = userRepository.findByUsername(name);

        if(user == null) {
            throw new BadCredentialsException("Authentication failed.");
        }

        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole()));

        return new UsernamePasswordAuthenticationToken(name, password, grantedAuthorities);
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.equals(UsernamePasswordAuthenticationToken.class);
    }
}

Основной класс приложения ...

@SpringBootApplication(exclude={
        HazelcastAutoConfiguration.class,
        DataSourceAutoConfiguration.class,
        SecurityAutoConfiguration.class
})
@EnableScheduling
@Slf4j
public class AwsorchestratorApplication implements CommandLineRunner{
  @Override
  public void run(String... arg0) throws Exception {
    if (arg0.length > 0 && arg0[0].equals("exitcode")) {
      throw new ExitException();
    }
  }

  public static void main(String[] args) throws Exception {
    if ( System.getProperty("spring.profiles.active") == null )
    {
      System.setProperty("spring.profiles.active","local");
    }
    new SpringApplication(AwsorchestratorApplication.class).run(args);
  }

  class ExitException extends RuntimeException implements ExitCodeGenerator {
    private static final long serialVersionUID = 1L;

    @Override
    public int getExitCode() {
      return 10;
    }
  }
}

UPDATE ONE :: ...

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private AppUserRepository userRepo;

    @Override
    public UserDetails loadUserByUsername(String username) {
        ApplicationUser user = userRepo.findByUsername(username);
        if(user == null) {
            throw new UsernameNotFoundException("User '" + username + "' not found.");
        }

        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(user.getRole());
        return new User(user.getUsername(), user.getPassword(), Collections.singletonList(grantedAuthority));
    }
}

1 Ответ

1 голос
/ 24 февраля 2020

Мне удалось исправить эту проблему, удалив мой пользовательский класс аутентификации (хотя я не думаю, что это на самом деле является частью проблемы), и отредактировав мою конфигурацию веб-безопасности в соответствии с приведенным ниже описанием.

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = package_location)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public CustomUserDetailsService detailsService;

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

    @Autowired
    public void configureGlobal (AuthenticationManagerBuilder auth) throws Exception {
        //the password encoder here is only to support a mix of encoding - that change can be removed
        auth.userDetailsService(detailsService).passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()
                .frameOptions()
                .disable()
                .and()
                .authorizeRequests()
                .antMatchers("/awsorchestrator/**")
                .hasAnyRole("ADMIN", "USER")
                .and()
                .formLogin()
                .usernameParameter("username")
                .passwordParameter("password")
                .and()
                .csrf()
                .disable();
    }
}

Важной частью, которая напрямую связана с моей проблемой, была часть passwordEncoder (PasswordEncoderFactories.createDelegatingPasswordEncoder ()). Мне также пришлось изменить пароль, хранящийся в базе данных, чтобы иметь префикс {bcrypt}, и теперь я могу войти без проблем.

Спасибо RG за советы.

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