Obtenir une erreur 404 lors de la tentative de connexion à l'aide d'Angular 6 & Spring Boot


Conor McGrath:

Obtention d'une erreur 40 (x) en essayant d'implémenter l'authentification Spring Boot pour un composant de connexion angulaire 6. Vous avez déjà une table client dans une base de données MySQL avec un nom client et un mot de passe.

Voici les fichiers sur lesquels je travaille pour essayer de résoudre le problème. La dernière image est l'erreur que j'obtiens après avoir saisi les données utilisateur de la table client.

Code de démarrage Java Spring

Contrôleur client

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api")
public class CustomerController {

    @Autowired
    CustomerRepository repository;

    @RequestMapping("/login")
    public boolean login(@RequestBody Customer user) {
        return
          user.getCname().equals("user") && user.getPassword().equals("password");
    }

    @RequestMapping("/user")
    public Principal user(HttpServletRequest request) {
        String authToken = request.getHeader("Authorization")
          .substring("Basic".length()).trim();
        return () ->  new String(Base64.getDecoder()
          .decode(authToken)).split(":")[0];
    }

    @GetMapping("/customers")
    public List<Customer> getAllCustomers() {
        System.out.println("Get all Customers...");

        List<Customer> customers = new ArrayList<>();
        repository.findAll().forEach(customers::add);

        return customers;
    }

    @PostMapping(value = "/customers/create")
    public Customer postCustomer(@RequestBody Customer customer) {

        Customer _customer = repository.save(new Customer(customer.getCname(), customer.getAddress(), customer.getPhone(),customer.getPassword()));
        return _customer;
    }

    @DeleteMapping("/customers/{cid}")
    public ResponseEntity<String> deleteCustomer(@PathVariable("cid") long cid) {
        System.out.println("Delete Customer with CID = " + cid + "...");

        repository.deleteByCid(cid);

        return new ResponseEntity<>("Customer has been deleted!", HttpStatus.OK);
    }

    @DeleteMapping("/customers/delete")
    public ResponseEntity<String> deleteAllCustomers() {
        System.out.println("Delete All Customers...");

        repository.deleteAll();

        return new ResponseEntity<>("All customers have been deleted!", HttpStatus.OK);
    }

    @GetMapping(value = "customers/cname/{cname}")
    public List<Customer> findByAge(@PathVariable String cname) {

        List<Customer> customers = repository.findByCname(cname);
        return customers;
    }

    @PutMapping("/customers/{cid}")
    public ResponseEntity<Customer> updateCustomer(@PathVariable("cid") long cid, @RequestBody Customer customer) {
        System.out.println("Update Customer with CID = " + cid + "...");

        Optional<Customer> customerData = repository.findByCid(cid);

        if (customerData.isPresent()) {
            Customer _customer = customerData.get();
            _customer.setCname(customer.getCname());
            _customer.setAddress(customer.getAddress());
            _customer.setPhone(customer.getPhone());
            return new ResponseEntity<>(repository.save(_customer), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }
}

Authentification

@Configuration
@EnableWebSecurity
public class BasicAuthConfiguration 
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
      throws Exception {
        auth
          .inMemoryAuthentication()
          .withUser("user")
          .password("password")
          .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) 
      throws Exception {
        http.csrf().disable()
          .authorizeRequests()
          .antMatchers("/login").permitAll()
          .anyRequest()
          .authenticated()
          .and()
          .httpBasic();
    }
}

Angular 6 / Code typographique

Composant de connexion

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Component({
    selector: 'login',
    templateUrl: './login.component.html'
})

export class LoginComponent implements OnInit {

    model: any = {};


    constructor(
        private route: ActivatedRoute,
        private router: Router,
        private http: HttpClient
    ) { }

    ngOnInit() {
        sessionStorage.setItem('token', '');
    }

    login() {
        const url = 'http://localhost:4200/login';
        this.http.post<Observable<boolean>>(url, {
            userName: this.model.username,
            password: this.model.password
        }).subscribe(isValid => {
            if (isValid) {
                sessionStorage.setItem('token', btoa(this.model.username + ':' + this.model.password));
                this.router.navigate(['']);
            } else {
                alert('Authentication failed.');
            }
        });
    }
}

Composant maison

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map, tap} from 'rxjs/operators';
@Component({
    selector: 'home',
    templateUrl: './home.component.html'
})

export class HomeComponent implements OnInit {

    userName: string;
    constructor(private http: HttpClient) { }

    ngOnInit() {
        const url = 'http://localhost:4200';

        const headers: HttpHeaders = new HttpHeaders({
            'Authorization': 'Basic ' + sessionStorage.getItem('token')
        });

        const options = { headers: headers };
        this.http.post<Observable<Object>>(url, {}, options).
            subscribe(principal => {
                this.userName = principal['name'];
            },
            error => {
                if (error.status === 401) {
                    alert('Unauthorized');
                }
            }
        );
    }

    logout() {
        sessionStorage.setItem('token', '');
    }
    private handleError(error: HttpErrorResponse) {
        if (error.error instanceof ErrorEvent) {
          console.error('An error occurred:', error.error.message);
        } else {
          console.error(
            `Backend returned code ${error.status}, ` +
            `body was: ${error.error}`);
        }
        return throwError(
          'Something bad happened; please try again later.');
      }
}

Erreur

Erreur

MaxKapralov:

Je pense que le problème est que vous essayez d'envoyer une demande à http://localhost:4200. Vous exécutez votre frontend sur ce port, mais votre backend s'exécute sur un autre. Peut-être que c'est 8080. Essayez de changer le port de l'URL de votre LoginComponent en 8080.

Articles connexes