【问题标题】:Spring Boot - How to fix Session bean with cors and spring securitySpring Boot - 如何使用 cors 和 spring security 修复 Session bean
【发布时间】:2019-12-16 16:53:10
【问题描述】:

TL;DR
每次 localhost:4200(通过 cors 过滤器)向 localhost:8080 发出 http 请求时,它都会丢失 sessionscope bean,该 bean 持有身份验证,这基本上使它无法使用 403 进行所有调用。排除第一个 http 请求(不落后于 Spring Security)

我有一个在 localhost:8080 中运行良好的 Spring Boot 应用程序。 我们正在其中创建一个有角度的 iframe,它也很有效(当部署在 localhost:8080 上时)

但是当我们在 localhost:4200 (ng serve) 上执行此操作时 它不会工作

它开始抱怨 cors,所以我有以下配置,除了我添加的关于 cors 的所有内容。

@Configuration
@Profile({"dev"})
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class springDevConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception{
    http.csrf().disable();
    http.headers().frameOptions().sameOrigin();
    http.headers().cacheControl().disable();
    http.cors().configurationSource(corsConfigurationSource())
    .and().authorizeRequests().anyRequest().permitAll();
  }

  @Bean
  public CorsConfigurationSource corsConfigurationSource(){
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration configuration = new CorsConfiguration();

    configuration.setAllowedOrigins(
    ImmutableList.of("http://localhost:4200"));

    configuration.setAllowedMethods(Arrays.asList(
    RequestMethod.GET.name(),
    RequestMethod.POST.name(),
    RequestMethod.OPTIONS.name(),
    RequestMethod.DELETE.name(),
    RequestMethod.PUT.name()));

    source.registerCorsConfiguration("/**", configuration);

    return source;
  }
}

我的会话 bean 相当简单

@Component
@SessionScope
public class UserSession {
   //Holds the Authorities for the prePostEnabled
   User user; 
   ...
}

为了初始化用户,我向某个端点(不受保护)发出请求并在代码中执行类似的操作

...
User user = new User(id, "", authorities);

Authentication auth = new UsernamePasswordAuthenticationToken(
user, null,authorities));

SecurityContextHolder.getContext().setAuthentication(auth);

Usersession.setUser(user);
...

当我在 localhost:8080 上发出 http 请求时,后续的 http 请求具有相同的会话

但是当我尝试从 localhost:4200 向 localhost:8080 发出请求时 每个请求似乎都获取不同的 UserSession / 可能会打开一个新会话?
(给我 403 上的所有受保护的端点)

真正发生了什么,为什么 localhost:4200 在向 localhost:8080 发出请求时会在每次调用时创建一个新会话? (以及应该更改哪些配置来解决此类问题?)

附录 1º:如果我发表评论

@EnableGlobalMethodSecurity(prePostEnabled = true)

该代码适用于 localhost:4200(我的意思是他不再拥有 403 代码)但可能仍在每个请求中使用另一个会话范围 bean

附录 2º
现在可以使用了
我所要做的就是将 ssl 放在 ng serve 配置中(它在 localhost:8080 但不是 4200)并且 JSessionId 开始工作!

【问题讨论】:

    标签: java spring spring-boot spring-security cors


    【解决方案1】:

    您能否详细说明如何嵌入 iframe 以及为原始页面提供什么服务?

    似乎正在发生的事情是,您实际上是在没有意识到的情况下发出跨域请求。 8080 和 4200 是不同的域,如果页面的一部分是从一个域加载的,而部分(即 iframe)从另一个域加载,则构成跨域请求,并且一个域发送的 cookie 不会应用于向其他,因此会话范围不共享。此外,如果您向非原始页面加载的域发出 Ajax 请求,则默认情况下它们会被拒绝,除非您设置了 CORS。这就解释了为什么你必须这样做。

    您必须确保页面的所有部分(包括 iframe 和 Ajax 请求)都是从同一个域加载的,或者您有其他方法可以将会话附加到请求中。通常,JSESSIONID cookie 用于此目的。这个 cookie 会在初始响应中发送吗?

    您通常有一个应用程序服务于前端,包括初始页面(例如 4200 上的应用程序),以及一个仅响应 API 调用的应用程序(例如 8080 上的应用程序),并配置了 CORS。这样,所有对后端的调用都是通过同一个域完成的,并且 cookie 可以正常应用。

    【讨论】:

    • 你好 Kaqqao,据我所知,我们根本不使用 localhost:8080 和 localhost:4200 的 cookie
    • @ioliano 修改答案
    • Kaqqao 看来你很厉害!在 localhost:8080 中,jsessionid 以某种方式存在并且在 iframe 调用中,但是当我从 localhost:4200 发出请求时,似乎缺少此 cookie!但是我还没有做任何配置来在 localhost:8080 上设置这个 cookie。所以我需要找到一种方法来获取 jsessionid 或在我不知道如何的角度上构建它,你有什么建议吗?
    • @ioliano JSESSIONID 是自动的,除非您明确禁用它。不要让事情变得不必要的复杂。如果要共享会话,请提供来自同一域的页面和 iframe。后端可以在不同的域上没有问题(只需配置 CORS)。
    • 在您帮助我找到问题时给您接受的答案
    猜你喜欢
    • 2019-07-16
    • 2021-11-06
    • 2020-05-29
    • 2015-06-11
    • 2017-09-09
    • 2022-10-07
    • 2021-06-26
    • 2020-09-30
    • 2021-10-30
    相关资源
    最近更新 更多