我已将我的应用程序上传到heroku:https://mystoryheroku.herokuapp.com
请尝试一下以解决问题。
一切似乎都有效,直到刷新网站。
JWT令牌已保存在LocalStorage中,但在页面刷新后会从“页眉”中丢失,
然后显示“访问被拒绝”错误。
通过将https://mystoryheroku.herokuapp.com粘贴到浏览器,令牌会再次发送到标头, 直到下一次刷新。
验证中间件:
const jwt = require('jsonwebtoken')
module.exports = function auth (req, res, next){
const token = req.header('auth-token');
if(!token) return res.status(401).send('Access Denied')
try{
const verified = jwt.verify(token, process.env.JWT_KEY)
req.user = verified;
next();
}catch(err){
res.status(400).send('Invalid Token');
}
}
一些路线示例:
//Get All Stories
storyRoute.route('/').get(verify,function(req, res){
Story.find(function(err, story){
if(err){
console.log(err);
}
else{
res.send(story);
}
});
});
//Get Stories by ID
storyRoute.route('/story/:id').get(verify,(req,res, next)=>{
Story.findById(req.params.id, function(err,story){
if(err){
res.status(500).json({
message: "Story not found!"
})
console.log( "Story not found!")
}
res.status(200).json({story});
});
});
//User Profile
userRoute.get('/profile',verify, (req, res)=> {
res.json({
message: 'Auth successful',
user:req.user
});
});
// User Profile (stories)
userRoute.get('/profile/mystories',verify,(req,res) =>{
Story.find({UserId: req.user._id})
.then(stories => {
res.status(200).json({
Stories:stories
});
});
});
服务示例:
getAllStories(){
const token = localStorage.getItem('id_token');
let headers = new HttpHeaders({
'Content-Type': 'application/json',
'auth-token': token
});
const httpOptions = {
headers: headers
};
return this.http.get(`${this.uri}/stories`,httpOptions)
}
getStoryById(id){
const token = localStorage.getItem('id_token');
let headers = new HttpHeaders({
'Content-Type': 'application/json',
'auth-token': token
});
const httpOptions = {
headers: headers
};
return this.http.get(`${this.uri}/stories/story/${id}`,httpOptions).pipe(map(res => res['story']))
}
getProfile(){
const token = localStorage.getItem('id_token');
let headers = new HttpHeaders({
'Content-Type': 'application/json',
'auth-token': token
});
const httpOptions = {
headers: headers
};
return this.http.get(`${this.uri}/profile`, httpOptions)
};
以此类推。
每次刷新后如何将令牌重新发送到标头?
非常感谢!
答案 0 :(得分:1)
您的错误与令牌无关。
我可以看到您将前端和后端托管在同一个域中(当然这不是问题)。
问题出在这里:
您的个人资料页面路径为/profile
。浏览器将向/profile
发送请求以获取要呈现的页面脚本。
但是获取用户个人资料的api端点也是/profile
。
因此,获取页面脚本的请求将到达端点以获取用户的个人资料(并且该请求不包含令牌),这就是为什么它发送Access denied error
的原因。
解决方案:
在后端api的所有端点上设置/api
前缀以避免这种冲突。
请检查以下帖子,了解如何在express中设置/api
前缀:
答案 1 :(得分:0)
我在您的网站上创建了一个帐户。似乎localStorage按预期工作。问题是当您刷新页面时,没有JS可以将标头注入请求中。
这里有两种可能的解决方案:
答案 2 :(得分:0)
我刚刚在您的网站上创建了用户,并浏览了一些链接,它似乎按预期运行;
检查下面的图像,第二个“个人资料”页面传递令牌。
问题仅在您执行硬刷新时,然后请求才直接发送到服务器,因此在这种情况下,它应返回初始html(可能您可以使用'/ api /'标记api路径),然后在前端,您的应用应根据网址重新加载数据
答案 3 :(得分:0)
对于将来的读者: 解决方案是将/ api添加到server.js中的所有路由以及服务中, 但最重要的是:https://medium.com/wineofbits/angular-2-routing-404-page-not-found-on-refresh-a9a0f5786268
在app-routing.module.ts中的: RouterModule.forRoot(routes,{useHash:true}) 会在网址中添加“ /#”。
没有它,该应用程序就无法运行。.
答案 4 :(得分:-1)
在页面重新加载和刷新之间,本地存储不存在。相反,您可以使用Session Storage。
来自文档:
只要打开浏览器,页面会话就会持续,并且在 页面重新加载和还原。
还要注意
在新标签页或窗口中打开页面会创建一个新会话,其中包含 顶级浏览上下文的值,这与 会话Cookie起作用。