Angular 6 Basic Auth возвращает 401 от клиента - PullRequest
0 голосов
/ 20 ноября 2018

Так что я уже некоторое время искал ответ на свою проблему и пробовал много предложений, но я не могу найти ответ.

Проблема в том, что когда я использую Почтальон дляпроверив, работает ли базовая аутентификация, я получаю обратно код 200, и все это хорошо, но как только я пытаюсь пройти аутентификацию, используя свой компонент входа, я возвращаю код 401 и говорю: «Для доступа к этому ресурсу требуется полная аутентификация».

Я довольно новичок в Angular и совершенно новичок в использовании Basic Auth, поэтому я понятия не имею, почему он работает с Postman и почему он не работает из приложения.

Любая помощь приветствуется

Ниже приведены соответствующие коды

log-in.component.ts:

onLogin(form: NgForm) {
    /* ... */
    let headers = new Headers();
    let userCredentials = user.userName + ":" + user.password;
    headers.append("Origin", "http://localhost:8080");
    headers.append("Authorization", "Basic " + btoa(userCredentials));

    return this.http.post('http://localhost:8080/api/users/login', headers).subscribe(
      (response) => {
        /* ... */
      },
      (error) => {
        console.log(error);
      }
    );
}

Конечная точка на стороне сервера:

@PostMapping(LOG_IN)
public ResponseEntity<User> login() {
    return ResponseEntity.ok().build();
}

WebSecurityConfig:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors()
                .and()
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/h2/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .httpBasic()
                .authenticationEntryPoint(getBasicAuthEntryPoint())
                .and()
            .headers()
                .frameOptions().disable()
                .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Autowired
    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
            .withUser("admin").password("1234").roles("ADMIN");
    }

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    protected void configureAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
    }

    @Bean
    public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint(){
        return new CustomBasicAuthenticationEntryPoint();
    }

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

CustomBasicAuthenticationEntryPoint:

public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {

    @Override
    public void commence(final HttpServletRequest request, 
            final HttpServletResponse response, 
            final AuthenticationException authException) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName() + "");

        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401 : " + authException.getMessage());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("MY REALM");
        super.afterPropertiesSet();
    }
}

MyUserDetailsService:

@Service
public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AuthenticatedUser authenticatedUser;

    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<User> oUser = userRepository.findByUserName(username);

        if (!oUser.isPresent()) {
            throw new UsernameNotFoundException(username);
        }

        User user = oUser.get();
        authenticatedUser.setUser(user);
        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
    grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().toString()));

        return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(), grantedAuthorities);
    }
}

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Вам необходимо передать заголовки в качестве 3-го параметра для метода post.Второе - это тело

return this.http.post('http://localhost:8080/api/users/login', {}, {headers}).subscribe(
  (response) => {

Если вы используете angular 6, вам действительно следует использовать новый класс HttpClient, старый класс Http устарел

0 голосов
/ 20 ноября 2018

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

protected void configure(HttpSecurity http) throws Exception
{
     http
    .csrf().disable()
    .authorizeRequests()
      .antMatchers(HttpMethod.OPTIONS,"/path/to/allow").permitAll()//allow CORS option calls
      .antMatchers("/resources/**").permitAll()
      .anyRequest().authenticated()
    .and()
    .formLogin()
    .and()
    .httpBasic();
}
...