使用JWT和本地存储安全访问路由

时间:2019-04-24 10:57:14

标签: node.js express jwt ejs

我正在构建一个小型应用程序,用户可以在其中登录并重定向到/ profile。现在,我从本地存储中获取JWT并通过服务器对其进行检查。然后,服务器将其发送回客户端,以告诉我这是否是有效会话。

jQuery / Client:

  UserController.initPanel = () => {
    if (session === null) {
     window.location = "/";
    } else {
      UserController.requestAuth(session);
    }
  };

  UserController.requestAuth = (sessionToken) => {
    var settings = {
      "url": "/api/auth", 
      "method": "POST",
      "headers": {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${sessionToken}`,
      },
      "data": ""
    }

    $.ajax(settings).done(function (response) {
      console.log(response);
    });
  };

Node.js / auth.js路由:

router.post("/",  (req, res) => {
    const authHeader = req.headers.authorization;
    if (typeof authHeader !== 'undefined') {
        const bearerToken = authHeader.split(' ')[1];
        verifyToken(bearerToken, (authData) => {
            tokenRequest(authData, (authResponse) => {
                handleAuthResponse(req, res, authResponse);
            })
        });
    }
});

const handleAuthResponse = (req, res, authResponse) => {
    console.log(authResponse);
    return res.status(200).json(authResponse);
}


const verifyToken = (token, cb) => {
    jwt.verify(token, 'mysecret', (err, authData) => {
    if (err) {
        res.sendStatus(403)
    } else {
        cb(authData);
    }
    });
}

const tokenRequest = (authHeader, cb) => {
    //console.log(authHeader);
    var config = {
        headers: {'Authorization': `bearer ${authHeader.token}`}
    };
    axios.get('https://myapi.dev/api/session/me', config)
    .then((res) => {
      if (res.data.error) {
        return response.data
      } else {
        cb(res.data);
      }
    })
    .catch((error) => {
      console.log('error', error);
    }); 

}

我觉得这不是正确的方法。我正在使用ejs渲染模板:

router.get("/profile", (req, res) => {
  const settings = {
    title: "Profile",
    revslider: false
  };
  res.render("profile/profile", { settings: settings } );
});

如果由于某种原因禁用了JS,那么/ profile仍然可以访问。没什么大问题,只是感觉不对。

那么,是否可以访问/ profile路由,在渲染之前先安全地检查授权服务器端?

此外,auth.js返回一些我可以在.ejs模板中使用的用户数据。因此,这也是我还要在渲染之前尝试检查auth的另一个原因。

编辑:

我不使用身份验证中间件,因为我不确定如何传递令牌?

module.exports = (req, res, next) => {
    try {
        const decoded = jwt.verify(req.body.token, 'mysecret');
        req.token = decoded;
    } catch (error) {
        console.log(error);
        return res.status(401).json({
            message: 'Auth Failed'
        }); 
    }
    next();
}

1 个答案:

答案 0 :(得分:0)

非常简单的middleware实现,下面利用了expressexpress-session

我们基本上创建了一个简单的函数来检查req.session是否存在,在该对象中,您可以使用一些标识用户是否已经过身份验证的东西。建议您在此处添加自己的逻辑,以进一步检查用户状态。

const authCheckMiddleware = (req, res, next) => {
  // Perform auth checking logic here, which you can attach
  // to any route.
  if(!req.session) {
      return res.redirect('/');
  }

  next();
};

authCheckMiddleware可以通过routeapp.use附加到任何router.usereq对象将传递给所有中间件。

// Use the authCheckMiddleware function
router.use('/profile', authCheckMiddleware);

您的router.get('/profile')呼叫现在已受到上述中间件的保护。

// Route protected by above auth check middleware
router.get("/profile", (req, res) => {
  const settings = {
      title: "Profile",
      revslider: false
  };

  res.render("profile/profile", { settings: settings } );
});