SpringBook + Vue JS + Spring Security Cookie 未通过

Posted

技术标签:

【中文标题】SpringBook + Vue JS + Spring Security Cookie 未通过【英文标题】:SpringBook + VueJS + SpringSecurity Cookie is not passed 【发布时间】:2020-08-28 07:27:44 【问题描述】:

我正在使用 SpringBoot2 和 VueJS 创建一个项目。我正在使用自定义 JWT 令牌进行授权。当用户登录时,我在响应“AUTH_TOKEN=tokenValue”中设置了一个 cookie。我预计来自 VueJS 的每个调用(使用 fetch)都会将该 cookie 传递给 SpringBoot,但并非所有端点都能获得 cookie。

当我使用 RestTemplate 和 Postman 测试 SpringBoot 时,cookie 传递得很好,并且端点可以正常工作。当我使用 VueJS 网站时,cookie 仅传递到我的 SecurityConfig 中具有“permitAll”的端点。

我还验证了我的 VueJS 始终在发送 cookie(我使用 php 端点对此进行了测试,并且 cookie 始终存在)。因此,当我使用浏览器并且并非所有端点都有 cookie 时,会发生一些事情。这是我的配置以及我如何使用它:

安全配置:

@Configuration
open class SecurityConfig(private val jwtTokenProvider :JwtTokenProvider) : WebSecurityConfigurerAdapter() 


    @Bean
    override fun authenticationManagerBean(): AuthenticationManager 
        return super.authenticationManagerBean()
    

    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) 
        //@formatter:off
        http
                .httpBasic().disable()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/thisEndpointDoesGetTheCookie").permitAll()
                .anyRequest().authenticated() //Anything else does not
                .and()
                .apply(JwtConfigurer(jwtTokenProvider))
        //@formatter:on
    


当我使用 permitAll 设置另一个端点时,该端点也开始获取令牌(在我的 jwtConfigurer/provider 中)

调用是使用 fetch 和 VueJS 完成的

这是我的注销示例(与任何其他端点相同)

    logout() 
      fetch('http://localhost:8100/auth/logout', 
            method: "post",
            headers: 
              'Accept': 'application/json',
              'Content-Type': 'application/json'
            
            ,credentials: 'include', //Yes I'm including the credentials
            body: ""
          ).then(res => 
            console.log("Logout was successful");
          ).catch(error => 
              console.log(error.message);
              console.log("Logout failed");
          );
    ,

这是我在用户登录时设置cookie的方式。我可以在浏览器中看到它

    // create a cookie
    val cookie = Cookie("AUTH_TOKEN", signedInUser.token)

    // expires in 30 days
    cookie.maxAge = 30 * 24 * 60 * 60
    // optional properties
    cookie.secure = authTokenCookieSecure //false for localhost
    cookie.isHttpOnly = true
    cookie.path = "/"
    // add cookie to response
    response.addCookie(cookie)

当我使用 TestRestTemplate(来自我的测试)或我正在使用 postman 端点的行为符合预期。

val headers = HttpHeaders()
headers["Cookie"] = "AUTH_TOKEN=$jwtToken"

我错过了什么?

【问题讨论】:

【参考方案1】:

出现问题是因为您必须在 Spring Security 中配置 CORS。 对于自定义标题,您必须在 Access-Control-Expose-Headers 中设置标题名称。

示例解决方案代码:

@Bean
fun corsConfigurationSource(): CorsConfigurationSource 
    val configuration = CorsConfiguration().applyPermitDefaultValues()
    configuration.allowedOrigins = listOf("*")
    configuration.allowedMethods = HttpMethod.values().map  it.name 
    configuration.allowedHeaders = listOf("*")
    configuration.exposedHeaders = listOf("AUTH_TOKEN")
    val source = UrlBasedCorsConfigurationSource()
    source.registerCorsConfiguration("/**", configuration)
    return source

此 CORS 配置允许任何域访问您的标头。这是DEV环境的好解决方案。对于 PROD,您应该指定来源而不是提供 *。

链接:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

【讨论】:

感谢您的回复。你快到了。但这还不足以修复它。问题是“fetch”和“axios”使用“OPTIONS”请求类型执行“飞行前”请求并且它不发送cookie。如果该调用成功,那么他们会执行完整的请求。所以我不得不允许所有“OPTIONS”调用不被验证。稍后我将发布完整的解决方案。 ``` .antMatchers(HttpMethod.OPTIONS,"/**").permitAll() //允许从浏览器进行 PreFlight 检查 ``

以上是关于SpringBook + Vue JS + Spring Security Cookie 未通过的主要内容,如果未能解决你的问题,请参考以下文章

Pygame错误:self.spritedict [spr] = surface_blit(spr.image,spr.rect)

SpringBoot rest-api+Vue CORS跨域.md

leo--study

初识SpringMVC

(私人收藏)Vue.js手册及教程

vue引用并使用本地js(局部引用,全局引用)