关于CORS:https://www.ruanyifeng.com/blog/2016/04/cors.html

preflight

先提前了解:预检请求。

客户端代码,浏览器访问127.0.0.1,然后在浏览器控制台运行

async function asd(){
await fetch('http://192.168.190.1:5555/', {
method: 'POST',
headers:{"asd":"sad"}
})
}

服务端代码

const express = require('express')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')

const PORT = 5555
const app = express()


app.use(bodyParser.urlencoded({ extended: true }))
app.use(cookieParser())

app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization,asd');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});

app.all('/', (req, res) => {
console.log(req.method)
console.log(req.headers)
res.send('ok')
})

app.listen(PORT, '0.0.0.0', () => {
console.log(`listen on ${PORT}`)
})

image-20231031083322692.png
两次请求,第一次是浏览器自动发的预检请求,第二次才是实际请求。

预检请求获取请求头里的Access-Control-Allow-Origin,Methods,Headers,以此决定实际请求能不能正常发送。

image-20231031083353137.png
注释掉服务端代码这部分res.header('Access-Control-Allow-Origin', '*');,客户端发请求失败。

Access to fetch at ‘http://192.168.190.1:5555/‘ from origin ‘http://127.0.0.1‘ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

浏览器何时携带cookie

NAME=VALUE 赋予 Cookie 的名称和其值(必需项)
expires=DATE Cookie 的有效期(若不明确指定则默认为浏览器关闭前为止)
path=PATH 将服务器上的文件目录作为Cookie的适用对象(若不指定则默 认为文档所在的文件目录)
domain=域名 作为 Cookie 适用对象的域名 (若不指定则默认为创建 Cookie 的服务器的域名)
Secure 仅在 HTTPS 安全通信时才会发送 Cookie
HttpOnly 加以限制, 使 Cookie 不能被 JavaScript 脚本访问

总结:设置cookie时,该cookie有对应的domain和path。domain包括host和port。访问domain/path或者domain/path/path1时才会携带对应的cookie。

访问http://192.168.190.1/myctf/,打开控制台,分别发送下面两个请求,然后查看请求头。

flag=1的path是/,访问http://192.168.190.1/http://192.168.190.1/myctf都会带。

async function asd(){
document.cookie='flag=1;path=/'
await fetch('http://192.168.190.1', {
method: 'POST'
})
}
asd()

flag1=2的path是/myctf,访问http://192.168.190.1/不会带。

async function asd(){
document.cookie='flag1=2'
await fetch('http://192.168.190.1', {
method: 'POST'
})
}
asd()

fetch 携带cookie问题

测试发现,headers里面放cookie,怎么样都不携带。

headers:{"Cookie":"flag=1"}

关于credentials: 'include'

自己的理解:浏览器发请求时是否带cookie要看domain和path,而domain即host:port

加了credentials: 'include',domain只包括host。所以满足host相同,path为path及其子path时,就带cookie。

测试

当前位置是http://192.168.190.1/,这样能带cookie。

如果把credentials去掉就不能带

async function asd(){
document.cookie='flag1=2'
await fetch('http://192.168.190.1:5555', {
method: 'POST',
credentials: 'include'
})
}
asd()

当前位置是http://192.168.190.1/myctf加了credentials也无法带cookie。因为path不满足

async function asd(){
document.cookie='flag1=2'
await fetch('http://192.168.190.1:5555', {
method: 'POST',
credentials: 'include'
})
}
asd()

当前位置是http://192.168.190.1/myctf加了credentials可以带cookie。此时path满足

async function asd(){
document.cookie='flag1=2'
await fetch('http://192.168.190.1:5555/myctf', {
method: 'POST',
credentials: 'include'
})
}
asd()