当前位置: 首页 > 知识库问答 >
问题:

Spring Boot-如何修复会话bean与cors和Spring安全

郭鸿信
2023-03-14

TL;DR
每次localhost:4200(通过cors过滤器)都会发出超文本传输协议请求localhost:8080它会丢失持有身份验证的会话范围bean,这基本上会使403的所有调用失败。不包括第一个超文本传输协议请求(它不支持Spring安全)

我有一个Spring Boot应用程序,它在localhost:8080中运行良好。我们正在其内部创建一个角度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; 
   ...
}

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

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

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

SecurityContextHolder.getContext().setAuthentication(auth);

Usersession.setUser(user);
...

当我在localhost:8080上发出超文本传输协议请求时,后续的超文本传输协议请求具有相同的会话。

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

到底发生了什么?为什么localhost:4200在向localhost:8080发出请求时,每次调用都要进行新会话?(为了解决此问题,应该更改哪些配置?)

增编1:如果我评论

@EnableGlobalMethodSecurity(prePostEnabled = true)

代码在localhost:4200上运行良好(我的意思是他不再有403个代码),但很可能仍然在每个请求中使用另一个会话范围bean

附录2:
它现在可以工作了
我所要做的就是将ssl放入ng serve配置中(它在本地主机上有:8080,但不是4200),JSessionId开始工作了!

共有1个答案

钱安和
2023-03-14

你能再展示一下你是如何嵌入iframe的,以及什么服务于原始页面的吗?

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

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

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

 类似资料:
  • 我需要确保给定的 bean 是使用会话范围定义的。 我知道我可以使用或,其中是我的(Web)Application Context,但是,没有。 如果你想知道为什么我需要这样的东西,请检查这个问题。 相关:我可以以编程方式确定Spring bean是否不是单例吗?

  • 问题内容: 这是我的工作方式 然后在 假设用户名是。然后,如果单击,将设置为Peter的用户对象,然后重定向到配置文件页面,该页面现在从中呈现信息。我只想使用创建相同的效果,因此想到了GET请求。所以我这样做 然后该方法就返回 剩下的就是创建一个servlet,捕获该,查询数据库以获取设置为重定向的对象。这是我的servlet 现在我有了,如何访问会话bean来查询数据库中的,然后访问受管Bean

  • 我正在尝试使用Hazelcast分布式缓存来复制带有Spring Boot&Spring Security的HTTP会话,但无法进行设置(不过,简单的缓存复制工作良好,我已经通过在一个应用程序节点的map中设置一些值并尝试在其他集群节点上获得它来验证了这一点)。 我已经通过网页上的东西,但不幸的是,我无法设置这一点。应用程序在集群中运行时,在一个节点上登录后,我没有在其他节点上获取会话对象(我正在

  • 问题内容: 有状态会话bean和HTTP会话之间有什么关系吗?我们将需要有状态会话Bean的用例是什么,而HTTP会话需要哪些用例。我可以将有状态会话Bean公开为静态Web服务吗? 问题答案: HTTP是一种无状态协议, 这意味着 它是服务器和客户端之间的实际传输协议- 是“无状态的, 因为它在调用之间不记得任何东西。 现在,首先阅读一下什么是HTTPSession和什么是Session Bea

  • 我的REST API使用Spring会话和Spring Security性,但是当我通过一个简单的过滤器启用CORS时遇到了一个问题。 如果我通过http代理使用相对URI(映射http://xxxx/api 对于客户端应用程序中的/api),它运行良好。 如果我直接使用完整的URL,我在使用CORS时遇到了一个问题,它无法获取会话信息,下面是Spring Security日志 我正在使用Spri

  • 我正在使用Spring Boot、Spring Security性和spring会话(redis)构建spring REST web应用程序。我正在使用SpringCloud和zuul代理按照网关模式构建一个云应用程序。在这个模式中,我使用spring会话来管理redis中的HttpSession,并使用它来授权我的资源服务器上的请求。当执行更改会话权限的操作时,我希望更新该对象,以便用户不必注销