如何在不发送其他身份验证请求的情况下保持跨源(CORS)Spring安全性的登录会话

问题描述 投票:0回答:1

我有一个受Spring安全保护的Spring Boot应用服务器。首次登录时,将使用用户名和密码对用户进行身份验证。如果我使用Spring MVC(相同来源),则不必在每次调用API时都重新登录。但是,当我从Angular应用程序(跨域)调用API时,每次刷新页面时都必须提供授权。

是否可以在每次刷新页面时保持登录会话而不必发送身份验证?我需要某种HTTP拦截器服务来手动检查来自Spring服务器的响应吗?

我尝试调用的REST API

@CrossOrigin(origins = "http://localhost:4200")
@RestController
public class TestControllers {
    private final AtomicLong counter = new AtomicLong();

    @GetMapping("/greeting")
    public MessageModel greeting (@RequestParam(value = "name", defaultValue = "World") String name) {
        return new MessageModel(counter.incrementAndGet(),"Hello, " + name + "!");
    }

    private class MessageModel{
        private long id;
        private String content;
        //Constructor, getter & setter
    }
}

Auth controller

@RestController
@RequestMapping("/api/v1")
public class BasicAuthController {

    @GetMapping(path = "/basicauth")
    public AuthenticationModel basicauth() {
        return new AuthenticationModel("You are authenticated");
    }

    class AuthenticationModel {
        private String message;
        //Constructor, getter & setter
    }
}

安全配置

@Configuration
@EnableWebSecurity(debug = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
                .authorizeRequests()
                    .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                    .antMatchers("/**").permitAll()
                    .anyRequest().authenticated()
                .and()
                    .httpBasic();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        auth.inMemoryAuthentication()
                .passwordEncoder(encoder)
                .withUser("user")
                .password(encoder.encode("asdasd"))
                .roles("USER");
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

Angular身份验证服务

authenticationService(username: string, password: string) {
    return this.http.get('http://localhost:8080/api/v1/basicauth',
      { headers: { authorization: this.createBasicAuthToken(username, password) } }).pipe(map((res) => {
      this.username = username;
      this.password = password;
      this.registerSuccessfulLogin(username, password);
    }));
  }
java spring spring-boot spring-security cross-domain
1个回答
0
投票

您需要为Angular客户端提供拦截器,因此请像下面这样创建一个新的可注入对象:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private authenticationService: AuthenticationService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const username = this.authenticationService.username; //get your credentials from wherever you saved them after authentification
    const password = this.authenticationService.password;
    if (username && password) {
      request = request.clone({
        setHeaders: {
          Authorization: this.createBasicAuthToken(username, password),
        }
      });
    }
    return next.handle(request);
  }
}

并将其添加到位于providers中的app.module.ts

{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},

这会将身份验证数据添加到每个请求中,因此您不必每次都登录。

© www.soinside.com 2019 - 2024. All rights reserved.