страница перезагрузки выдает ошибку 401 при использовании Spring Security angular и остальных API - PullRequest
1 голос
/ 10 марта 2020

У меня относительно простая установка с использованием Spring Boot, Spring Security и клиента angular. Так что я использую api rest, чтобы показать базу данных на клиенте, как веб-сайт базы данных

, поэтому на данный момент вход в систему работает, и когда я вхожу в систему, я могу все без проблем. но когда я перезагружаю страницу, я потерял разрешение для остальных API, я больше не могу получить информацию с ошибкой 401.

это после процесса входа в систему

General
Request URL: http://localhost:8080/mindnessBdd/api/v1/films
Request Method: GET
Status Code: 200 
Remote Address: [::1]:8080
Referrer Policy: no-referrer-when-downgrade

Request header
GET /mindnessBdd/api/v1/films HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Accept: application/json, text/plain, */*
Sec-Fetch-Dest: empty
Authorization: Basic bWluZG5lc3M6QFJhcGhhNzY2MjAh
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
Content-Type: application/json
Origin: http://localhost:4200
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Referer: http://localhost:4200/films
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7

Responce header
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json
Date: Tue, 10 Mar 2020 09:32:31 GMT
Expires: 0
Pragma: no-cache
Transfer-Encoding: chunked
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

и после перезагрузки

General
Request URL: http://localhost:8080/mindnessBdd/api/v1/films
Request Method: GET
Status Code: 401 
Remote Address: [::1]:8080
Referrer Policy: no-referrer-when-downgrade

Response Headers
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Tue, 10 Mar 2020 09:37:25 GMT
Expires: 0
Pragma: no-cache
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
WWW-Authenticate: Basic realm="Realm"
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

Request Header
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
Authorization: Basic dW5kZWZpbmVkOnVuZGVmaW5lZA==
Connection: keep-alive
Content-Type: application/json
Host: localhost:8080
Origin: http://localhost:4200
Referer: http://localhost:4200/films
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36

не знаю, может ли это помочь, но это мой конфиг аутентификации

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .authorizeRequests()
                .antMatchers("/", "/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().formLogin().disable();;

    }
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();

        configuration.setAllowedOrigins(ImmutableList.of("http://localhost:4200"));
        configuration.setAllowedMethods(ImmutableList.of("*"));
        configuration.setAllowCredentials(true);
        configuration.setMaxAge((long) 3600);
        configuration.setAllowedHeaders(ImmutableList.of("*"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

Я предполагаю, что мое непонимание Spring Security здесь ошибочно, Кто-нибудь может увидеть, что я сделал не так?

спасибо заранее!

** изменить компонент входа:

Skip to content
Search or jump to…

Pull requests
Issues
Marketplace
Explore

@mindness 
mindness
/
WebAppFront
1
00
 Code Issues 0 Pull requests 0 Actions Projects 0 Wiki Security Insights Settings
WebAppFront/src/app/login/login.component.ts / 
 raphael lefrancois login / auth / logout
c3fe322 4 days ago
Executable File  39 lines (33 sloc)  1 KB

Code navigation is available!
Navigate your code with ease. Click on function and method calls to jump to their definitions or references in the same repository. Learn more

You're using code navigation to jump to definitions or references.
Learn more or give us feedback
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { AuthenticationService } from './auth.service';

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

  username: string;
  password: string;
  errorMessage = 'Invalid Credentials';
  successMessage: string;
  invalidLogin = false;
  loginSuccess = false;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private authenticationService: AuthenticationService) {   }

  ngOnInit() {
  }

  handleLogin() {
    this.authenticationService.authenticationService(this.username, this.password).subscribe((result) => {
      this.invalidLogin = false;
      this.loginSuccess = true;
      this.successMessage = 'Login Successful.';
      this.router.navigate(['/films']);
    }, () => {
      this.invalidLogin = true;
      this.loginSuccess = false;
    });
  }

}


authservice

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';

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

  // BASE_PATH: 'http://localhost:8080'
  USER_NAME_SESSION_ATTRIBUTE_NAME = 'authenticatedUser'

  public username: string;
  public password: string;

  constructor(private http: HttpClient) {

  }

  authenticationService(username: string, password: string) {
    return this.http.get(`http://localhost:8080/mindnessBdd/api/v1/basicauth`,
      { headers: { authorization: this.createBasicAuthToken(username, password) } }).pipe(map((res) => {
      this.username = username;
      this.password = password;
      this.registerSuccessfulLogin(username, password);
    }));
  }

  createBasicAuthToken(username: string, password: string) {
    return 'Basic ' + window.btoa(username + ':' + password);
  }

  registerSuccessfulLogin(username, password) {
    sessionStorage.setItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME, username);
  }

  logout() {
    sessionStorage.removeItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME);
    this.username = null;
    this.password = null;
  }

  isUserLoggedIn() {
    const user = sessionStorage.getItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME)
    if (user === null) { return false; }
    return true;
  }

  getLoggedInUserName() {
    const user = sessionStorage.getItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME)
    if (user === null) { return ''; }
    return user;
  }
}

http перехватчик

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AuthenticationService } from './auth.service';

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {

  constructor(private authenticationService: AuthenticationService) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (this.authenticationService.isUserLoggedIn() && req.url.indexOf('basicauth') === -1) {
      const authReq = req.clone({
        headers: new HttpHeaders({
          'Content-Type': 'application/json',
          Authorization: `Basic ${window.btoa(this.authenticationService.username + ':' + this.authenticationService.password)}`
        })
      });
      return next.handle(authReq);
    } else {
      return next.handle(req);
    }
  }
}

1 Ответ

0 голосов
/ 11 марта 2020

это очень интересный вопрос.

Если вы внимательно изучите два заголовка запроса (один после входа в систему и один после перезагрузки), вы найдете причину.

один после входа в систему имеет Авторизацию, закодированную Base64 как:

Authorization: Basic bWluZG5lc3M6QFJhcGhhNzY2MjAh

один после перезагрузки:

Authorization: Basic dW5kZWZpbmVkOnVuZGVmaW5lZA==

теперь, если вы декодируете вторую авторизацию в обычный текст, это:

undefined:undefined

И вот почему вы получили 401, так как undefined undefined не является действительным пользователем и паролем.

И я полагаю, что вы получили имя пользователя и пароль из переменной javascript, которая не определяется при перезагрузке страницы ...


update: после прочтения кода внешнего интерфейса Похоже, вы сохранили имя пользователя в хранилище сеанса, и при перезагрузке страницы предполагается, что пользователь вошел в систему, поскольку находит имя пользователя в хранилище сеанса. поэтому он пытается отправить токен снова, однако имя пользователя и пароль в службе аутентификации не установлены. Вы можете сохранить имя пользователя и токен в хранилище сессии (cook ie). А при перезагрузке он может получить токен из хранилища. И чтобы это было безопасно, установите флаг HttpOnly.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...