页面刷新后JWT令牌丢失

时间:2020-07-29 14:20:03

标签: angular jwt

我已将我的应用程序上传到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)
  
    };

以此类推。

每次刷新后如何将令牌重新发送到标头?

非常感谢!

5 个答案:

答案 0 :(得分:1)

您的错误与令牌无关。

我可以看到您将前端和后端托管在同一个域中(当然这不是问题)。

问题出在这里:

您的个人资料页面路径为/profile。浏览器将向/profile发送请求以获取要呈现的页面脚本。

但是获取用户个人资料的api端点也是/profile

因此,获取页面脚本的请求将到达端点以获取用户的个人资料(并且该请求不包含令牌),这就是为什么它发送Access denied error的原因。

解决方案

在后端api的所有端点上设置/api前缀以避免这种冲突。

请检查以下帖子,了解如何在express中设置/api前缀:

How to add prefix to all node / express routes

答案 1 :(得分:0)

我在您的网站上创建了一个帐户。似乎localStorage按预期工作。问题是当您刷新页面时,没有JS可以将标头注入请求中。

这里有两种可能的解决方案:

  1. 如果这是SPA(似乎是SPA),则不要在提供HTML的子页面上检查JWT。
  2. 使用Cookie。它们将自动附加到每个请求。

答案 2 :(得分:0)

我刚刚在您的网站上创建了用户,并浏览了一些链接,它似乎按预期运行;

检查下面的图像,第二个“个人资料”页面传递令牌。

问题仅在您执行硬刷新时,然后请求才直接发送到服务器,因此在这种情况下,它应返回初始html(可能您可以使用'/ api /'标记api路径),然后在前端,您的应用应根据网址重新加载数据

enter image description here

答案 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起作用。