Spring Security GET http://localhost:8081/login net::ERR_TOO_MANY_REDIRECTS 302 Angular和Java

332nm8kg  于 2023-06-23  发布在  Spring
关注(0)|答案(1)|浏览(197)

我使用Spring Security v6.1.0在Java中实现了身份验证,这是端点:

@GetMapping(value="/loginUser")
    public User login(Principal principal) {
        return this.userService.findByEmail(principal.getName());
    }

WebSecurityConfig类:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .cors().and().csrf().disable()
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers("/", "/login").permitAll()
                        .requestMatchers("/scan",
                                "/loginUser",
                                "/users",
                                "/invoices",
                                "/dueNextWeek",
                                "/groupedByVendor",
                                "/groupedByVendorTotalAmountPerMonth",
                                "/totalAmountPerMonth").authenticated()
                )
                .formLogin((form) -> form
                        .loginPage("/login")
                        .loginProcessingUrl("/login")
                        .defaultSuccessUrl("/loginUser")
                        .permitAll()
                )
                .cors((cors) -> cors
                        .configurationSource(corsConfigurationSource())
                );

        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }

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

用户服务实施:

@Override
    public User findByEmail(String email) {
        Optional<User> user = this.userRepository.findByEmail(email);
        return user.get();
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<User> userOpt = userRepository.findByEmail(username);
        User user = userOpt.orElseThrow(() -> new UsernameNotFoundException(username + " not found!"));

        return org.springframework.security.core.userdetails.User.builder()
                .username(user.getEmail())
                .password(user.getPassword()).build();
    }

Angular服务:

import {Component} from '@angular/core';
import {Router} from "@angular/router";
import {AuthService} from "../authentication/auth.service";

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent {

  form: any = {
    username: null,
    password: null
  };

  isLoggedIn = false;
  errorMessage = '';
  wrongCredentials: boolean = false;
  invalidLogin: boolean = false;

  constructor(private router: Router, private loginService: AuthService) {
  }

  onSubmit(): void {
    sessionStorage.setItem('username', this.form.username);
    sessionStorage.setItem('password', this.form.password);

    this.loginService.authenticate(this.form.username, this.form.password).subscribe(
      () => {
        this.router.navigate(['/home']);
        this.invalidLogin = false;
      },
      (err) => {
        this.invalidLogin = true;
        this.wrongCredentials = true;
      }
    )
  }
}
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {catchError, map, throwError} from "rxjs";

const AUTH_API = 'http://localhost:8081/login';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  isLoggedIn: boolean | undefined;

  constructor(private http: HttpClient) {
  }

  ngOnInit(): void {
  }

  authenticate(username: string, password: string) {
    const httpOptions: Object = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'Authorization': "Basic " + btoa(username + ":" + password)
      }),
      responseType: 'text'
    };

    let credentials = {username: username, password: password};

    return this.http.post(AUTH_API, credentials, httpOptions).pipe(
      map(() => {
          let authString = 'Basic ' + btoa(username + ':' + password);
          sessionStorage.setItem('username', username);
          sessionStorage.setItem('basicAuth', authString);

          this.isLoggedIn = true;
        }),
      catchError((error) => {
        console.error('Authentication error:', error);
        return throwError(error);
      }))
  }

  isUserLoggedIn() {
    let basicAuth = sessionStorage.getItem('basicAuth');
    return basicAuth != null;
  }

  logOut() {
    sessionStorage.removeItem('username');
    sessionStorage.removeItem('basicAuth');

    this.isLoggedIn = false;
  }
}

当我从postman向/login上的java应用程序发送POST请求时,我得到了经过身份验证的User作为响应,我猜它应该如何工作,但是当我从angular应用程序发送请求时,我得到了GET http://localhost:8081/login net::ERR_TOO_MANY_REDIRECTS 302。我哪里做错了?

6qqygrtg

6qqygrtg1#

我找到问题了。这段代码

.formLogin((form) -> form
                        .loginPage("/login")
                        .loginProcessingUrl("/login")
                        .defaultSuccessUrl("/loginUser")
                        .permitAll()
                )

导致了HTTP 302循环。我修改了filterChain方法:

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and().csrf()
                .disable()
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers(HttpMethod.OPTIONS, "/**")
                .permitAll()
                        .requestMatchers("/login")
                .permitAll()
                        .requestMatchers(
                            //all other urls listed
                        ).authenticated());
        return http.build();

现在的终点是:

@RequestMapping(value="/login")
public ResponseEntity<User> login(@RequestBody LoginUserDTO loginUserDTO) {
     return ResponseEntity.ok(this.userService.findByEmail(loginUserDTO.username()));
}

localhost:8081/login发出POST请求现在工作得非常好。

相关问题