英文:
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="/loginUser")
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) -> 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();
}
The angular service:
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;
}
}
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) -> 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(
//所有其他列出的URL
).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
请求可以正常工作。
英文:
I have found the problem. This piece of code
.formLogin((form) -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/loginUser")
.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) -> authorize
.requestMatchers(HttpMethod.OPTIONS, "/**")
.permitAll()
.requestMatchers("/login")
.permitAll()
.requestMatchers(
//all other urls listed
).authenticated());
return http.build();
And the endpoint now is:
@RequestMapping(value="/login")
public ResponseEntity<User> login(@RequestBody LoginUserDTO loginUserDTO) {
return ResponseEntity.ok(this.userService.findByEmail(loginUserDTO.username()));
}
Making POST
requests to localhost:8081/login
works perfectly fine now.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论