背景:最近有个需求是需要用 node 模拟我们网站的客户端请求拿到数据,但是每个请求都需要登录成功后携带 cookie 的 sessionId 才能正常发送,那么怎样才能用 node 去模拟客户端的单点登录,拿到 cookie 呢?
用浏览器查看了一下登录的整个过程,首先,输入完用户名密码,cas 服务器会给一个 ticket 的东西,然后带着这个 ticket 去访问重定向的地址,这个时候,cas 服务器就会把 JSESSIONID 传递回来了,自动保存到浏览器的 cookie 中。
最终解决办法:使用 puppeteer (类似爬虫)模拟用户登录,登录成功后获取网站的 cookie
话不多说,上代码!
const puppeteer = require('puppeteer');
let loginUrl = 访问地址;
const user = 登录名;
const password = 密码;
let cookie;
(async () => {
const browser = await puppeteer.launch({headless: true});//打开浏览器, headless 为 false 的时候,可以看见浏览器的整个过程
const page = await browser.newPage();//打开一个空白页
await page.goto(loginUrl);//打开网站
await page.type('input[name="username"]', user); // 输入用户名的 input (也可以是其他的选择器)
await page.type('input[name="password"]', password); // 输入密码的 input (也可以是其他的选择器)
await page.click('button'); // 点击登录的按钮 (也可以是其他的选择器)
await page.waitForNavigation({
waitUntil: 'load',
timeout: 0
});//等待页面加载出来,等同于window.onload
const cookies = await page.cookies();
cookies.map(v => {
if (v.name === 'JSESSIONID') {
cookie = v.value; // 这个就是登录成功后得到的 cookie 里的 JSESSIONID
--- 下面的代码是我要把用户的信息和 JSESSIONID 存到一个公共文件里,用不到的可以忽略以下代码 ---
let data = {
"username": 用户名,
"cookie": "JSESSIONID="+ cookie +"; Path=/; HttpOnly"
}
fs.writeFile('./user.json', JSON.stringify(data), (err) => {
if (err) {
console.log(err);
} else {
console.log('存入 user 信息成功!');
}
})
}
});
await browser.close();//关掉浏览器
})();ps:这里记录一个坑,使用 puppeteer load 的网页可能很大,需要很长的时间,超时了以后会在命令行报错
TimeoutError: Navigation Timeout Exceeded: 30000ms exceeded解决办法:
把 timeout 设置为 0 参考连接
await page.waitForNavigation({
waitUntil: 'load',
timeout: 0
});