GET http://localhost:8081/login net::ERR_TOO_MANY_REDIRECTS 302 Angular and Java

huangapple go评论73阅读模式
英文:

GET http://localhost:8081/login net::ERR_TOO_MANY_REDIRECTS 302 Angular and Java

问题

我使用Spring Security v6.1.0在Java中实现了身份验证,以下是相关代码部分:

在Java端,我实现了身份验证,使用了Spring Security v6.1.0,以下是相关代码部分:

@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();
    }
}

UserServiceImpl 类:

@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 发送POST请求到Java应用程序时,我会得到认证的User作为响应,我认为这是正常工作的方式,但是当我从Angular应用程序发送请求时,我得到了 GET http://localhost:8081/login net::ERR_TOO_MANY_REDIRECTS 302。我做错了什么?

英文:

I implemented authentication in Java using Spring Security v6.1.0 and this is the endpoint:

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

WebSecurityConfig class:

@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) -&gt; authorize
.requestMatchers(&quot;/&quot;, &quot;/login&quot;).permitAll()
.requestMatchers(&quot;/scan&quot;,
&quot;/loginUser&quot;,
&quot;/users&quot;,
&quot;/invoices&quot;,
&quot;/dueNextWeek&quot;,
&quot;/groupedByVendor&quot;,
&quot;/groupedByVendorTotalAmountPerMonth&quot;,
&quot;/totalAmountPerMonth&quot;).authenticated()
)
.formLogin((form) -&gt; form
.loginPage(&quot;/login&quot;)
.loginProcessingUrl(&quot;/login&quot;)
.defaultSuccessUrl(&quot;/loginUser&quot;)
.permitAll()
)
.cors((cors) -&gt; cors
.configurationSource(corsConfigurationSource())
);
return http.build();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(&quot;http://localhost:4200&quot;));
configuration.setAllowedMethods(Arrays.asList(&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, &quot;DELETE&quot;));
configuration.setAllowedHeaders(Arrays.asList(&quot;*&quot;));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration(&quot;/**&quot;, configuration);
return source;
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

UserServiceImpl:

 @Override
public User findByEmail(String email) {
Optional&lt;User&gt; user = this.userRepository.findByEmail(email);
return user.get();
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional&lt;User&gt; userOpt = userRepository.findByEmail(username);
User user = userOpt.orElseThrow(() -&gt; new UsernameNotFoundException(username + &quot; not found!&quot;));
return org.springframework.security.core.userdetails.User.builder()
.username(user.getEmail())
.password(user.getPassword()).build();
}

The angular service:

import {Component} from &#39;@angular/core&#39;;
import {Router} from &quot;@angular/router&quot;;
import {AuthService} from &quot;../authentication/auth.service&quot;;
@Component({
selector: &#39;app-login&#39;,
templateUrl: &#39;./login.component.html&#39;,
styleUrls: [&#39;./login.component.css&#39;]
})
export class LoginComponent {
form: any = {
username: null,
password: null
};
isLoggedIn = false;
errorMessage = &#39;&#39;;
wrongCredentials: boolean = false;
invalidLogin: boolean = false;
constructor(private router: Router, private loginService: AuthService) {
}
onSubmit(): void {
sessionStorage.setItem(&#39;username&#39;, this.form.username);
sessionStorage.setItem(&#39;password&#39;, this.form.password);
this.loginService.authenticate(this.form.username, this.form.password).subscribe(
() =&gt; {
this.router.navigate([&#39;/home&#39;]);
this.invalidLogin = false;
},
(err) =&gt; {
this.invalidLogin = true;
this.wrongCredentials = true;
}
)
}
}
import {Injectable} from &#39;@angular/core&#39;;
import {HttpClient, HttpHeaders} from &quot;@angular/common/http&quot;;
import {catchError, map, throwError} from &quot;rxjs&quot;;
const AUTH_API = &#39;http://localhost:8081/login&#39;;
@Injectable({
providedIn: &#39;root&#39;
})
export class AuthService {
isLoggedIn: boolean | undefined;
constructor(private http: HttpClient) {
}
ngOnInit(): void {
}
authenticate(username: string, password: string) {
const httpOptions: Object = {
headers: new HttpHeaders({
&#39;Content-Type&#39;: &#39;application/json&#39;,
&#39;Authorization&#39;: &quot;Basic &quot; + btoa(username + &quot;:&quot; + password)
}),
responseType: &#39;text&#39;
};
let credentials = {username: username, password: password};
return this.http.post(AUTH_API, credentials, httpOptions).pipe(
map(() =&gt; {
let authString = &#39;Basic &#39; + btoa(username + &#39;:&#39; + password);
sessionStorage.setItem(&#39;username&#39;, username);
sessionStorage.setItem(&#39;basicAuth&#39;, authString);
this.isLoggedIn = true;
}),
catchError((error) =&gt; {
console.error(&#39;Authentication error:&#39;, error);
return throwError(error);
}))
}
isUserLoggedIn() {
let basicAuth = sessionStorage.getItem(&#39;basicAuth&#39;);
return basicAuth != null;
}
logOut() {
sessionStorage.removeItem(&#39;username&#39;);
sessionStorage.removeItem(&#39;basicAuth&#39;);
this.isLoggedIn = false;
}
}

When I send POST request from postman to the java application on /login, I get the authenticated User as a response, which I guess it works how it should work, but when I send a request from the angular application, I get GET http://localhost:8081/login net::ERR_TOO_MANY_REDIRECTS 302. Where do I go wrong?

答案1

得分: 2

我已经找到了问题。这段代码

.formLogin((form) -&gt; form
.loginPage(&quot;/login&quot;)
.loginProcessingUrl(&quot;/login&quot;)
.defaultSuccessUrl(&quot;/loginUser&quot;)
.permitAll()
)

导致了HTTP 302循环。我已经更改了filterChain方法:

    @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf()
.disable()
.authorizeHttpRequests((authorize) -&gt; authorize
.requestMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
.permitAll()
.requestMatchers(&quot;/login&quot;)
.permitAll()
.requestMatchers(
//所有其他列出的URL
).authenticated());
return http.build();

现在的端点是:

@RequestMapping(value=&quot;/login&quot;)
public ResponseEntity&lt;User&gt; login(@RequestBody LoginUserDTO loginUserDTO) {
return ResponseEntity.ok(this.userService.findByEmail(loginUserDTO.username()));
}

现在向localhost:8081/login发送POST请求可以正常工作。

英文:

I have found the problem. This piece of code

.formLogin((form) -&gt; form
.loginPage(&quot;/login&quot;)
.loginProcessingUrl(&quot;/login&quot;)
.defaultSuccessUrl(&quot;/loginUser&quot;)
.permitAll()
)

was causing the HTTP 302 loop. I have changed the filterChain method:

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

And the endpoint now is:

@RequestMapping(value=&quot;/login&quot;)
public ResponseEntity&lt;User&gt; login(@RequestBody LoginUserDTO loginUserDTO) {
return ResponseEntity.ok(this.userService.findByEmail(loginUserDTO.username()));
}

Making POST requests to localhost:8081/login works perfectly fine now.

huangapple
  • 本文由 发表于 2023年6月22日 15:43:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529611.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定