java - 如何在不发送另一个身份验证请求的情况下保持来自跨源(CORS)Spring security的登录 session

标签 java spring spring-boot spring-security cross-domain

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

是否可以保留我的登录 session ,而不必每次刷新页面时都发送身份验证?我是否需要某种 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
    }
}

身份验证 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);
    }));
  }

最佳答案

您的 Angular 客户端需要一个拦截器,因此请像这样创建一个新的注入(inject):

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

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

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

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

关于java - 如何在不发送另一个身份验证请求的情况下保持来自跨源(CORS)Spring security的登录 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62368879/

相关文章:

java - Apache CXF 日志记录

java - MapStruct 根据目标类型映射正确的对象实例

java - 如何在 GraphQL Java 上拆分模式

java - 没有 Spring Boot 的 Spring Boot 执行器

java - 什么是空运算符?

java - Maven 版本 :update not updating the given version, 与存储库进行比较并更新到最新版本而不是给定版本

java - 使用 for 语句和 while 语句向前移动迭代器之间的区别

java - Maven:缺少 Artifact org.springframework:spring:jar:4.2.6

java - 当我请求休息服务时,Jquery 不起作用(Spring Boot)

java - 使用Gradle解压缩Jar文件时,如何显示文件夹?