使用 Vue Axios (CORS) 发送/存储会话 cookie 时出现问题

Posted

技术标签:

【中文标题】使用 Vue Axios (CORS) 发送/存储会话 cookie 时出现问题【英文标题】:Problem sending/storing session cookie with Vue Axios (CORS) 【发布时间】:2020-11-08 16:23:10 【问题描述】:

由于某种原因,我无法从我的 Flask 后端(端口 5000)存储会话 cookie,并通过 Axios 从我的 Vue 前端(端口 8082)将其作为凭据发送。我在前端创建了一个全局 axios,然后登录获取会话 cookie,然后尝试执行需要身份验证的请求。我看到 cookie 收到来自 /login 的响应,但是当发出下一个请求时它不包含它,导致 401。请求与 Postman 一起工作正常,所以我认为问题在于 CORS 以某种方式阻止发送凭据。

main.js(设置Axios的全局实例)

Vue.prototype.$http = Axios;
Vue.prototype.$http.defaults.withCredentials = true

auth.js(用于登录和获取 cookie 的 Vuex 模块)

this._vm.$http.post(backendUrl+'/api/login', 
  email: formEmail,
  password: formPassword,
   headers: 'Content-type': 'application/json'
)
.then(function (response) 
  console.log(response.data);
  router.push('profile');
  commit(types.UPDATE_AUTH_SIGN_USER_SUCCESS, response)
  commit(types.UPDATE_AUTH_FORM_PASSWORD, '')
  commit(types.UPDATE_AUTH_FORM_EMAIL, '')
  commit(types.RESET_APP_LOADING)
)

Profile.Vue(要求会话 cookie 身份验证的请求不起作用,401)

  this.$http.get(backendUrl+'/api/user/gdpr/fetch', function (response) 
    console.log(response);
    if (response.data == 0) 
      context.dialogGDPR = true;
    
    context.$store.commit(types.UPDATE_APP_IS_LOADING, false)
  )

对于 Flask 后端,我使用以下方法激活 CORS:

app.py

CORS(app, origins='http://127.0.0.1:8082', supports_credentials=True)
app.config['CORS_HEADERS'] = 'Content-Type'

对于每个已定义的请求:

@cross_origin(origins='http://127.0.0.1:8082', supports_credentials=True)

【问题讨论】:

您能看到在应用程序选项卡中设置和更新的 cookie 吗?您是否也尝试过创建一个实例并将其添加到原型而不是完整的 axios 对象,就像这样。 ``` import axios from 'axios' const instance = axios.create( withCredentials: true ) Vue.prototype.$http = instance; ``` @HimanshuPant 我不明白如何使用应用程序选项卡,但我检查了存储选项卡,那里没有 cookie。我尝试使用您建议的实例,但仍然得到 401 并且没有会话 cookie。 我写了一篇关于在 CORS here 中使用 cookie 的常见问题解答条目,它可能会帮助您找到问题所在。同一站点上还有一个标头检查器,可以检查您的响应标头是否为 CORS 正确设置了 cookie。如果这没有帮助... 1. 您能否检查任何控制台错误/警告并将它们包含在问题中? 2. 你能说出你测试过的确切浏览器版本吗? 3. 您能否发布登录请求的响应标头,尤其是与 cookie 和 CORS 相关的标头? 【参考方案1】:

这就是正在发生的事情。您发送一个登录请求,您的服务器创建一个会话并在客户端上设置一个 cookie,但在您的情况下,客户端不是浏览器,而是 xhr 对象(由 axios 创建),因此很快就会被清除您的浏览器不知道会话,因此它不会保存 sessionId,因此没有凭据可以与未来的请求一起发送。 要解决此问题,您有以下选择。

    尝试按原样提交表单,而不使用 axios 或任何 javascript。在您的表单上设置method="post"action="<url_to_login_endpoint> 属性,然后让它发疯。您的提交将由浏览器处理并保存 sessionID。 为您的后端研究基于令牌的身份验证(我不知道烧瓶,所以我不知道它是如何工作的),这将是一个完整的 SPA 和无状态解决方案。

我不知道业务逻辑和约束,但我建议设置 Token Auth,因为我认为这是理想且更安全的,但如果您只是一起破解它,请选择选项 1

【讨论】:

我认为会话 cookie 应该以某种方式与 axios 一起工作,否则为什么会有 withCredentials 选项? axios 对此没有解决方案似乎很奇怪。 withCredentials 是用于发送现有会话身份验证 cookie 的标志,而不是设置这些 cookie。不是真的 axios 而是 xhr【参考方案2】:

所以在前端的Vue中你需要设置参数withCredentialstrue 使用axios时axios.get("http://localhost:8081/shop/hello",withCredentials:true)

在您的服务器端 API 上,您需要启用 CORS 并将标头 Access-Control-Allow-Credentials 添加到 HttpResponse 中,例如 Access-Control-Allow-Credentials=true

在 CORS 上设置 Cookie 的问题是它们需要由浏览器使用 Set-Cookie 标头属性正确创建,您需要添加所有属性,否则不会创建。 我在创建 Vue.js 和 Spring-Boot 应用程序时遇到了同样的问题。

这就是我在 Java 中创建 Cookie 服务器端的方式,但您可以手动创建它,也可以使用您使用的任何语言创建它,

因此,如果Set-Cookie 标头未设置属性或无效,则浏览器无法正确创建 Cookie 可能会出现问题,至少这是我在短时间内发现的,但它对我有用. 我希望这会有所帮助。

 Cookie cookie = new Cookie("NewRandomCookie",UUID.randomUUID());
 cookie.setPath("/");
 cookie.setMaxAge(3600);
 c.setSecure(false);
 c.setHttpOnly(true);
 cookie.setDomain("localhost");
 
 servletResponse.addCookie(c);

这是我的服务器响应标头,因此您可以看到它在浏览器中的外观,我在这里使用 Chrome。我认为您在这里看到的所有属性都是必需的,如果您设置属性“安全”并且您需要设置站点域以便之后访问 cookie,则不会设置 cookie。

 Request Header

 Request URL: http://localhost:8081/shop/hello
 Request Method: GET
 Status Code: 200 
 Remote Address: [::1]:8081
 Referrer Policy: strict-origin-when-cross-origin

 Response Header

 Access-Control-Allow-Credentials: true
 Access-Control-Allow-Origin: http://localhost:8080
 Connection: keep-alive
 Content-Type: application/json
 Date: Tue, 10 Nov 2020 23:10:30 GMT
 Keep-Alive: timeout=60
 Set-Cookie: JSESSIONID=6D1C6D23F775A1F650842E55AC0A6E3C; Path=/; HttpOnly
 ->
 Set-Cookie: NewRandomCookie=0fdeba77-072d-4a87-9bc3-f041b2ef138a; Max- 
 Age=3600; Expires=True, 10-Nov-2020 23:47:32 GMT; Domain=localhost; Path=/; 
 HttpOnly;
 <-
 Transfer-Encoding: chunked
 Vary: Origin
 Vary: Access-Control-Request-Method
 Vary: Access-Control-Request-Headers
 
 

【讨论】:

以上是关于使用 Vue Axios (CORS) 发送/存储会话 cookie 时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

CORS 使用“授权”标头和数据阻止 axios 请求

axios发送两次请求原因及解决方法

在 vue 中使用 axios 的 Cors 和预检错误

Vue/Axios CORS 成功但响应为空

使用 Vue.js 和 Axios 向 Mailchimp 提交表单会导致 CORS 错误

在vue中使用axios的Cors和预检错误