Vue Axios (CORS) 的问题 sending/storing 会话 cookie
Problem sending/storing session cookie with Vue Axios (CORS)
出于某种原因,我无法存储来自我的 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)
这是正在发生的事情。你发送一个 post 请求登录,你的服务器创建一个会话并在客户端上设置一个 cookie,但在你的情况下,客户端不是浏览器而是 xhr 对象(由 axios 创建),它很快就会被清除,因此您的浏览器不知道该会话,因此它不会保存 sessionId,因此没有凭据可以与未来的请求一起发送。
要解决这个问题,您有以下选择。
- 尝试按原样提交表单,不使用 axios 或任何 javascript。在您的表单上设置
method="post"
和 action="<url_to_login_endpoint>
属性,让它变得疯狂。您的提交将由浏览器处理并保存 sessionID。
- 为您的后端研究基于令牌的身份验证(我不知道 flask,所以我不知道它是如何工作的),这将是一个完整的 SPA 和无状态解决方案。
我不知道业务逻辑和约束,但我建议设置 Token Auth,因为我认为这是理想且更安全的,但如果您只是一起破解它,请选择选项 1
所以在 Vue on front-end 你需要设置参数 withCredentials
true
使用 axios axios.get("http://localhost:8081/shop/hello",{withCredentials:true})
时
在您的 server-side API 上,您需要启用 CORS 并将 header Access-Control-Allow-Credentials
添加到 HttpResponse,就像这样 Access-Control-Allow-Credentials=true
关于通过 CORS 设置 Cookie 的事情是它们需要由浏览器使用 Set-Cookie
header 属性正确创建,您需要添加所有属性,否则它不会被创建.
我在创建 Vue.js & Spring-Boot 应用程序时遇到了同样的问题。
这就是我在 Java 中创建 Cookie 服务器端的方式,但您可以手动创建它或使用您使用的任何语言创建它,
因此,如果 Set-Cookie
header 没有设置属性或无效,浏览器可能会出现无法正确创建 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);
这是我的服务器响应 Header 所以你可以看到它在浏览器中的样子,我在这里使用 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
出于某种原因,我无法存储来自我的 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)
这是正在发生的事情。你发送一个 post 请求登录,你的服务器创建一个会话并在客户端上设置一个 cookie,但在你的情况下,客户端不是浏览器而是 xhr 对象(由 axios 创建),它很快就会被清除,因此您的浏览器不知道该会话,因此它不会保存 sessionId,因此没有凭据可以与未来的请求一起发送。
要解决这个问题,您有以下选择。
- 尝试按原样提交表单,不使用 axios 或任何 javascript。在您的表单上设置
method="post"
和action="<url_to_login_endpoint>
属性,让它变得疯狂。您的提交将由浏览器处理并保存 sessionID。 - 为您的后端研究基于令牌的身份验证(我不知道 flask,所以我不知道它是如何工作的),这将是一个完整的 SPA 和无状态解决方案。
我不知道业务逻辑和约束,但我建议设置 Token Auth,因为我认为这是理想且更安全的,但如果您只是一起破解它,请选择选项 1
所以在 Vue on front-end 你需要设置参数 withCredentials
true
使用 axios axios.get("http://localhost:8081/shop/hello",{withCredentials:true})
在您的 server-side API 上,您需要启用 CORS 并将 header Access-Control-Allow-Credentials
添加到 HttpResponse,就像这样 Access-Control-Allow-Credentials=true
关于通过 CORS 设置 Cookie 的事情是它们需要由浏览器使用 Set-Cookie
header 属性正确创建,您需要添加所有属性,否则它不会被创建.
我在创建 Vue.js & Spring-Boot 应用程序时遇到了同样的问题。
这就是我在 Java 中创建 Cookie 服务器端的方式,但您可以手动创建它或使用您使用的任何语言创建它,
因此,如果 Set-Cookie
header 没有设置属性或无效,浏览器可能会出现无法正确创建 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);
这是我的服务器响应 Header 所以你可以看到它在浏览器中的样子,我在这里使用 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