未传递SpringBook + VueJS + SpringSecurity Cookie [英] SpringBook + VueJS + SpringSecurity Cookie is not passed

查看:67
本文介绍了未传递SpringBook + VueJS + SpringSecurity Cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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打开类SecurityConfig(priv val jwtTokenProvider:JwtTokenProvider):WebSecurityConfigurerAdapter(){@豆角,扁豆重写fun authenticationManagerBean():AuthenticationManager {返回super.authenticationManagerBean()}@Throws(Exception :: class)覆盖有趣的configure(http:HttpSecurity){//@ formatter:offhttp.httpBasic().disable().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).和().authorizeRequests().antMatchers("/thisEndpointDoesGetTheCookie").permitAll().anyRequest().authenticated()//其他没有.和().apply(JwtConfigurer(jwtTokenProvider))//@ formatter:on}} 

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

该调用是使用 fetch 和VueJS

完成的

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

  logout(){fetch('http://localhost:8100/auth/logout',{方法:发布",标头:{'Accept':'application/json','内容类型':'应用程序/json'},credentials:'include',//是,我要包含凭据身体: ""}).then(res => {console.log(注销成功");}).catch(错误=> {console.log(error.message);console.log(登出失败");});}, 

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

 //创建一个cookieval cookie = Cookie("AUTH_TOKEN",signedInUser.token)//30天后到期cookie.maxAge = 30 * 24 * 60 * 60//可选属性cookie.secure = authTokenCookieSecure//对于本地​​主机为falsecookie.isHttpOnly = truecookie.path ="/"//将cookie添加到响应response.addCookie(cookie) 

当我使用TestRestTemplate(来自测试)进行呼叫时,或者当我使用邮递员,端点的行为符合预期.

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

我想念的是什么?

解决方案

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

示例解决方案代码:

  @Beanfun corsConfigurationSource():CorsConfigurationSource {val配置= 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("/**",配置)退货来源} 

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

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

I'm creating a project using SpringBoot2 and VueJS. I'm using a custom JWT token for authorisation. When the user logs in I set a cookie in the response "AUTH_TOKEN=tokenValue". I expected that every call from VueJS (using fetch) would pass that cookie to SpringBoot, but not all endpoints get the cookie.

When I test SpringBoot with RestTemplate and with Postman the cookie is passed just fine and the endpoint works. When I use the VueJS website, the cookie is only passed to endpoints that have "permitAll" in my SecurityConfig.

I have also verified that my VueJS is always sending the cookie (I used a php endpoint to test this and the cookie is always there). So something happens when I use the browser and not all endpoints have the cookie. Here is my Config and how I use it:

Security Config:

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

}

When I set another endpoint with permitAll then that endpoint starts getting the token too (in my jwtConfigurer/provider)

The call is done using fetch and VueJS

Here is my logout example (same as any other endpoint)

    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");
          });
    },

This is how I set the cookie when the user logs in. I can see it in the browser

    // 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)

When I make the call using TestRestTemplate (from my tests) or when I'm using postman the endpoints behave as expected.

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

What I'm I missing?

解决方案

Problem occurs because you have to configure CORS in Spring Security. For custom headers you have to set your header name in Access-Control-Expose-Headers.

Example solution code:

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

This CORS configuration allows any domain to access your header. It's good solution for DEV environment. For PROD you should specify origin instead of providing *.

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

这篇关于未传递SpringBook + VueJS + SpringSecurity Cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆