基于 Cookie 的身份验证适用于桌面浏览器,但不适用于移动浏览器
Cookie-based authentication works on desktop browsers but not on mobile ones
我正在为我的后端使用 express.js 和 Sequelize,我的授权路由如下所示:
exports.signin = (req, res) => {
Admin.findOne({
where: {
username: req.body.username
}
})
.then(admin => {
if (!admin) {
return res.status(404).send({
ERR: USER_NOT_FOUND
});
}
var passwordIsValid = bcrypt.compareSync(
req.body.password,
admin.password
);
if (!passwordIsValid) {
return res.status(401).send({
ERR: WRONG_PASSWORD
});
}
const tokenBody = {
id: admin.id,
isMaster: (admin.username == "Master")
};
var token = jwt.sign(tokenBody, process.env.JWT_SECRET, {
expiresIn: tokenExpirationTime
});
res.cookie('auth_token', token, {
// 'tokenExpirationTime' is in seconds (as required for JWT), but maxAge
// expects milliseconds, so it must be multiplied by 1000:
maxAge: tokenExpirationTime * 1000,
httpOnly: true,
secure: true
});
res.status(200).send({ success: true });
})
.catch(err => {
console.error(err);
res.status(500).send({
ERR: INTERNAL_SERVER_ERROR
});
});
};
我的前端使用 Ejs,我的登录代码是:
const signInUrl = '/api/auth/signin';
let form = document.getElementById('login');
form.onsubmit = async (e) => {
e.preventDefault();
let data = new FormData(form);
data = {
username: data.get('username'),
password: data.get('password')
};
axios.defaults.withCredentials = true
axios.post(signInUrl, data, { withCredentials: true })
.then(response => {
// Redirect to the home page:
if (response.data.success)
window.location.replace('/');
else // console.log(response.data);
informError(0);
})
.catch(error => {
console.error(error);
if (error.response) {
if (error.response.data && error.response.data.ERR)
informError(error.response.data.ERR);
else
informError(0);
} else {
informError(1);
}
});
}
现在的问题是系统在桌面浏览器上完全可以正常工作(我已经使用了一个多月了,它通过了各种测试)但在移动浏览器上却不行!
在移动设备上,我正在登录并成功将我重定向到主页,但之后,我仍在使用登录按钮,表明我没有登录。另外,我无法访问任何受保护的路线,收到“需要登录”错误!
任何帮助将不胜感激!
所以对于那些有同样问题的人,对我来说,当我尝试使用 [=16] 从我的 phone 访问服务器(在我的笔记本电脑“localhost:3000”上)时,问题就出现了=] 喜欢:http://192.168.0.107:3000
。我发现问题与受保护的 cookie (secure: true
) 有关,移动浏览器未使用它,因为我使用的是 http 而不是 https,但桌面浏览器通常使用它。所以我想在 https 协议的域上部署应用程序将解决这个问题。但出于测试目的,只需删除 secure: true
部分即可。
我正在为我的后端使用 express.js 和 Sequelize,我的授权路由如下所示:
exports.signin = (req, res) => {
Admin.findOne({
where: {
username: req.body.username
}
})
.then(admin => {
if (!admin) {
return res.status(404).send({
ERR: USER_NOT_FOUND
});
}
var passwordIsValid = bcrypt.compareSync(
req.body.password,
admin.password
);
if (!passwordIsValid) {
return res.status(401).send({
ERR: WRONG_PASSWORD
});
}
const tokenBody = {
id: admin.id,
isMaster: (admin.username == "Master")
};
var token = jwt.sign(tokenBody, process.env.JWT_SECRET, {
expiresIn: tokenExpirationTime
});
res.cookie('auth_token', token, {
// 'tokenExpirationTime' is in seconds (as required for JWT), but maxAge
// expects milliseconds, so it must be multiplied by 1000:
maxAge: tokenExpirationTime * 1000,
httpOnly: true,
secure: true
});
res.status(200).send({ success: true });
})
.catch(err => {
console.error(err);
res.status(500).send({
ERR: INTERNAL_SERVER_ERROR
});
});
};
我的前端使用 Ejs,我的登录代码是:
const signInUrl = '/api/auth/signin';
let form = document.getElementById('login');
form.onsubmit = async (e) => {
e.preventDefault();
let data = new FormData(form);
data = {
username: data.get('username'),
password: data.get('password')
};
axios.defaults.withCredentials = true
axios.post(signInUrl, data, { withCredentials: true })
.then(response => {
// Redirect to the home page:
if (response.data.success)
window.location.replace('/');
else // console.log(response.data);
informError(0);
})
.catch(error => {
console.error(error);
if (error.response) {
if (error.response.data && error.response.data.ERR)
informError(error.response.data.ERR);
else
informError(0);
} else {
informError(1);
}
});
}
现在的问题是系统在桌面浏览器上完全可以正常工作(我已经使用了一个多月了,它通过了各种测试)但在移动浏览器上却不行!
在移动设备上,我正在登录并成功将我重定向到主页,但之后,我仍在使用登录按钮,表明我没有登录。另外,我无法访问任何受保护的路线,收到“需要登录”错误!
任何帮助将不胜感激!
所以对于那些有同样问题的人,对我来说,当我尝试使用 [=16] 从我的 phone 访问服务器(在我的笔记本电脑“localhost:3000”上)时,问题就出现了=] 喜欢:http://192.168.0.107:3000
。我发现问题与受保护的 cookie (secure: true
) 有关,移动浏览器未使用它,因为我使用的是 http 而不是 https,但桌面浏览器通常使用它。所以我想在 https 协议的域上部署应用程序将解决这个问题。但出于测试目的,只需删除 secure: true
部分即可。