Ошибка входа в систему с пружинной загрузкой «ERR_TOO_MANY_REDIRECTS»

#angular #spring-boot #authentication

Вопрос:

Я хочу войти в систему с помощью Spring Boot и Angular, но я получаю строку «ERR_TOO_MANY_REDIRECTS». В бэкэнде есть функция repsonse, которая возвращает токены, имена пользователей, пароли и роли. Серверная часть работала с почтальоном, я не получил той же ошибки. Соответствующие коды являются следующими. В чем моя ошибка? Спасибо.

 HttpInterceptorService

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpHeaders, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { AuthenticationService } from './services/authentication.service';
import { catchError } from 'rxjs/operators';


@Injectable()
export class HttpInterceptorService implements HttpInterceptor {

    constructor(private authenticationService: AuthenticationService) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        const currentUser = this.authenticationService.currentUserValue;
        if (currentUser amp;amp; currentUser.generateToken) {
            request = request.clone({
                setHeaders: {
                    Authorization: `Basic ${currentUser.generateToken}`
                }
            });
        }

        return next.handle(request);
    }
}


AuthenticationService


import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
import { Observable, BehaviorSubject } from 'rxjs';
import { KullaniciKariyer } from '../models/cvModel/KulaniciKariyer';
import { JwtResponse } from '../models/JwtResponse';

const apiHost = environment.host;

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

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

  public username: String;
  public password: String;

  public currentUser: Observable<JwtResponse>;
  private currentUserSubject: BehaviorSubject<JwtResponse>;

  constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<JwtResponse>(JSON.parse(localStorage.getItem('currentUser')));
    this.currentUser = this.currentUserSubject.asObservable();
  }

  public get currentUserValue(): JwtResponse {
    return this.currentUserSubject.value;
  }

  login(tcKimlikNo: string, password: string): Observable<any> {
  
    return this.http.get<any>(apiHost   '/api/login').pipe(
      map(response => {
        if (response) {
          localStorage.setItem('currentUser', JSON.stringify(response));
          this.currentUserSubject.next(response);
        }
        return response;
      })
    );
  }

  logout() {
    localStorage.removeItem('currentUser');
    this.currentUserSubject.next(null);
  }

}


export class JwtResponse {
    generateToken: string;
    username: string;
    password: string;
    roles: string[] = [];
}


Guard  

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from "@angular/router";
import { Injectable } from "@angular/core";
import { AuthenticationService } from 'src/app/services/authentication.service';
import { KullaniciKariyer } from 'src/app/models/cvModel/KulaniciKariyer';
import { JwtResponse } from 'src/app/models/JwtResponse';

@Injectable()
export class LoginGuard implements CanActivate {


  currentUser: JwtResponse;

  constructor(private router: Router,
    private authenticationService: AuthenticationService) { }
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

    const currentUser = this.authenticationService.currentUserValue;
    if (currentUser) {
      // logged in so return true
      return true;
    }

    // not logged in so redirect to login page with the return url
    this.router.navigate(["anasayfa"]);
    return false;
  }

}


Login.componenet

onSubmit() {

    this.authenticationService.login(this.loginForm.value.username, this.loginForm.value.password)
      .subscribe(
        data => {
          
            this.invalidLogin = false;
            this.loginSuccess = true;
            this.successMessage = 'Success.';
            this.authenticationService.isAuthenticationFunc(true);
            sessionStorage.setItem('role', data.roles);
            this.router.navigate(['pages']);

        },
        error => {
          this.errorMessage = error.message;;
          this.loading = false;
        });
   
  }



Pages.Routing

const routes: Routes = [
  {
    path: '',
    component: PagesComponent,
    children: [
      
      {
        path: 'admin',
        loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),
        canActivate: [LoginGuard]
      },

      {
        path: 'editor',
        loadChildren: () => import('./editor/editor.module').then(m => m.EditorModule),
        canActivate: [LoginGuard]
      }
    ],
  }
];


AdminRouting.Routing

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class PagesRoutingModule { }


const routes: Routes = [
  {
    path: 'userCreate',
    component: UserCreateComponent,
    canActivate: [LoginGuard],
    data: { roles: [Constants.ROLE_ADMIN] }
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class AdminRoutingModule { }


EditorRouting.Routing

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class PagesRoutingModule { }


const routes: Routes = [
  {
    path: 'userList',
    component: UserListComponent,
    canActivate: [LoginGuard],
    data: { roles: [Constants.ROLE_EDITOR] }
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class EditorRoutingModule { }
 

Бэкэнд

 WebSecuritConfig

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        UserServiceImpl userServiceImpl;
    
        @Autowired
        private JwtTokenUtil jwtTokenUtil;
    
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder.userDetailsService(userServiceImpl).passwordEncoder(passwordEncoder());
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and().csrf().disable().
                    authorizeRequests()
                    .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                    .anyRequest().fullyAuthenticated()
                    .and()
                    .formLogin().loginPage("/api/login")
                    .and()
                    .httpBasic();
    
            http.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtTokenUtil));
    
        }
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurer() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
                }
            };
        }
    
    }
    ********************
    
    @Service
    @Transactional
    public class UserServiceImpl implements UserDetailsService {
    
        @Autowired
        private UserRepository userRepository;
    
        @Override
        public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
    
            User user = userRepository.findByuserName(userName);
    
            if (user == null) {
                throw new UsernameNotFoundException("User Name is not Found");
            }
    
            return new org.springframework.security.core.userdetails.User(user.getuserName(), user.getPassword(), getAuthority(user));
    
        }
    
        public List<SimpleGrantedAuthority> getAuthority(User user) {
    
            List<SimpleGrantedAuthority> authorities = user.getRoles().stream()
                    .map(role -> new SimpleGrantedAuthority(role.getRoleAdi()))
                    .collect(Collectors.toList());
    
            return authorities;
        }
    
    }


@GetMapping("/api/login")
        public ResponseEntity<?> login(Principal principal) {
            if (principal == null) {
                return ResponseEntity.ok(principal);
            }
            UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) principal;
            User user = userRepository.findByUsername(authenticationToken.getName());
    
            
            List<String> roles = user.getRoles().stream()
                    .map(role -> role.getRoleName())
                    .collect(Collectors.toList());
    
            return ResponseEntity.ok(new JwtResponse(jwtTokenUtil.generateToken(authenticationToken),
                    user.getUserName(),
                    user.getPassword(),
                    roles));
        }
 

Комментарии:

1. Вы используете formLogin? Можете ли вы поделиться конфигурацией веб-безопасности вашего приложения springboot?

2. Я снова отредактировал и добавил коды.

Ответ №1:

Вы получаете слишком много перенаправлений, потому что используете spring security со страницей входа /api/login/ и не разрешаете ее в конфигурации. Таким образом, spring security автоматически перенаправляет на страницу входа, но даже страница входа требует аутентификации, поэтому перенаправление происходит снова и снова. Вы можете исправить это, добавив permitAll() метод в конце блока formLogin.

    .formLogin()
      .loginPage("/api/login")
      .permitAll();
 

Но в идеале вы не должны использовать formlogin() . В .loginPage() явадоке говорится следующее:

 login page to redirect to if authentication is required
 

На этой странице входа в систему необходимо сделать запрос на публикацию /api/login с именем пользователя и паролем в теле запроса. Как только это будет сделано, вы будете перенаправлены на другие страницы. Поскольку вы используете angular, вместо этого вам понадобится api для входа в систему.

Вы можете проверить различные способы достижения углового входа в систему с помощью springboot

Кроме того, вы не передаете учетные данные пользователя из угловой формы.