我正在尝试使用JWT令牌创建登录。我已经为这个工作了好几天了,现在真的很困难。
这是我到目前为止所做的。
Login Request |确认用户名和密码正确,创建json web令牌并将其附加到仅http签名的cookie。然后使用数据通过json发送到前端。我可以从前端的json响应中成功访问用户数据。
const loginUser = async (req, res, next) => {
try {
const {username, password} = req.body
//grabbing user associated with our username
const user = await User.findOne({username:username})
//check if username and password come from the same user
if (user && (await bcrypt.compare(password, user.password))){
const token = generateToken(user._id) //creating a jwt token
//creating a cookie with our token in it
res.cookie('token', token, {
maxAge: 1000*60*15,
httpOnly: true,
signed: true
})
console.log(req.signedCookies)
//sending our user info to frontend via json
res.status(200).json({
_id: user._id,
name: user.username,
email: user.email,
})
} else {
res.status(400)
throw new Error('Invalid credentials')
}
} catch (error) {
next(error)
}
}
前端登录|登录表单工作,我成功地获得json数据没有问题。如果需要,我也可以将令牌附加到json数据,我知道如何做到这一点。
<h1>Login</h1>
<form id="login_form">
<label for="username">Username</label>
<input type="text" name="username">
<label for="password">Password</label>
<input type="password" for="password" name="password">
<button type="button" onclick="loginSubmit()">Submit</button>
</form>
<script>
const loginSubmit = async () => {
const loginForm = document.getElementById('login_form') //grabbing the login_form
const data = new URLSearchParams() // this can take in form data
//this for loop runs for each input field for the form passed into FormData()
for (const pair of new FormData(loginForm)){
data.append(pair[0], pair[1]) //pair[0] is the name of the input, pair[1] is the value
}
const response = await fetch('/user/login', {
method: 'POST',
body: data //passing the form data into our req.body
})
}
</script>
现在我的问题是什么?我已经确认每个请求都发送了cookie,并且在我的开发人员控制台中。我只是不明白在每个请求上验证用户的下一步需要做什么。我想我了解注销功能。我可以重写标记值,让它成为任意字符串。但是我不明白如何从前端验证cookie中的信息,也许我只是不理解整个过程。
任何帮助都太好了。感谢您的宝贵时间!
使用JWT令牌的一种常见方法是通过创建一个身份验证中间件来验证每个用户请求,该中间件在每次请求发送到受保护的路由时验证令牌。
例如
var cookieParser = require('cookie-parser');
app.use(cookieParser());
const auth = async (req, res, next) => {
try {
token = req.signedCookies.token;
if (token) {
res.locals.decodedData = jwt.verify(token, JWT_SECRET);
next();
} else {
res.status(401).json({message: 'not logged in'});
}
} catch (error) {
// jwt.verify() throws an error if the token is invalid
res.status(401).json({message: 'invalid token'});
console.log(error);
}
};
app.get('/super/secret/files', auth, givefiles);
这里next()函数只在令牌被验证后调用,这意味着/super/secret/files
路由中使用的giveFiles函数永远不会为未经身份验证的用户运行。
你也可以这样做:
app.use('/secret', auth);
app.get('/secret/file1', giveFile1);
app.get('/secret/file2', giveFile2);
这将自动对/secret
路由下的所有路径应用认证中间件。