【问题标题】:Best way to check route access检查路线访问的最佳方法
【发布时间】:2020-08-01 23:25:45
【问题描述】:

我的设置是这样的:我有一个 React 前端,它向快速服务器发出请求(显然基于节点)。 当用户登录时,他的凭据被检查并最终返回一个令牌,该令牌将用于执行进一步的操作。

所以这一切都很好,但我想防止用户绕过登录屏幕,只做 website.com/dashboard。我的第一个想法是检查应用程序中每个路由更改的令牌验证,但我不知道这样做是否正确。

每次路由改变的时候打个电话好像有点矫枉过正……不过不知道有没有更好的办法。仅仅检查令牌是否存在显然是不够的,因为用户可以在其中放入任何他们想要的东西。

他们将无法进行修改或获取数据,因为他们需要该令牌来向 API 发出请求,但是如果您可以通过手动编写路由来查看接口,那仍然很愚蠢。

到目前为止,这是我解决它的想法:

  • 在每次路由更改时调用数据库,这可能不是一个好主意。
  • 将令牌保存在 redux 中并使用它来进行调用。如果令牌不存在,只需重定向到登录页面。这看起来相当不错,但是人们可以从 devtools 或其他东西访问 redux 商店吗?或者这已经够难了,以至于他们不能轻易搞砸?

【问题讨论】:

    标签: reactjs express authentication


    【解决方案1】:

    如果您使用的是 express-session,则会在成功登录时设置一个名为 connect.sid 的 cookie,其中包含会话 ID。 您可以从 React 中的 cookie 中读取此会话 ID 的值,以检查用户是否已登录,并相应地阻止请求,而无需进行任何 API 调用。

    【讨论】:

    • 所以我猜你可以编辑那个cookie?如果有人只是在其中插入带有随机数据的 cookie 怎么办?
    【解决方案2】:

    你想怎么做是对的。这里有更多解释:

    您所说的称为授权(与身份验证不同),它处理用户可以访问或不可以访问的内容。您可以通过多种方式验证授权。

    使用会话 cookie 是一种方法。 但是......由于您正在构建 API,因此将前端和后端“分离”(有人说“不可知”)是一个好习惯,这意味着前端不应该知道任何关于后端的信息,反之亦然。这使得使用会话 cookie 并不理想(因为您在前端有 cookie,而有关会话的信息存储在后端)。

    因此,使用令牌 (JWT) 是处理授权的好方法。

    在您的情况下,您确实可以先对用户进行身份验证,然后将令牌存储在前端。

    然后,您可以像这样处理授权:

    1. 前端:在标头中发送带有所有请求的令牌(如果存在)。

    2. 后端:验证令牌。如果有效,让用户通过。如果没有,请向前端发送错误消息!

    3. 如果前端收到错误消息,请重定向到登录(或您想要的任何地方)。

    你是怎么做到的? (我将专注于后端。前端没有什么特别的)。

    在您的主应用文件(通常是 app.js)中:

    const express = require('express')
    
    const publicRoutes = require('./routes/publicroutes')
    const privateRoutes = require('./routes/privateroutes')
    
    const defineAuth = require('./helpers/defineauth')
    const isAuth = require('./helpers/isAuth')
    
    const app = express()
    
    app.use(defineAuth)
    
    app.use('/publicRoute', publicRoutes) // like /login, /signup, etc...
    app.use(isAuth)
    app.use('/privateRoute', privateRoutes) // accessible only with a valid token
    

    在defineAuth中间件中:

    1. 验证是否有授权头

    2. 验证令牌

      defineauth 中间件:

      const jwt = require('jsonwebtoken')
      module.exports = (req, res, next) => {
        const authHeader = req.get('Authorization')
        if (!authHeader) {
          req.isAuth = false
          return next()
        }
        const token = authHeader.split(' ')[1]
        let decodedToken
        try {
          decodedToken = jwt.verify(token, process.env.JWT_KEY)
        } catch (err) {
          req.isAuth = false
          return next()
        }
        if (!decodedToken) {
          req.isAuth = false
          return next()
        }
        // Here, the token is valid so :
        req.isAuth = true
        next()
      }
      

    然后,您可以轻松地检查代码中的任何位置,如果用户被授权或未授权。在这里我签入 app.js。

    isAuth middleware : 
    const isAuth = (req, res, next) => {
      if (!req.isAuth) {
        const error = new Error('Authorization required')
        error.status = 401
        throw error
      }
      next()
    }
    
    module.exports = isAuth
    

    您可以在任何地方验证授权。这样一来,处理不同级别的授权变得更加容易(例如,如果您有免费和高级用户)。

    【讨论】:

    • 感谢您的精彩回答!
    猜你喜欢
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 2011-07-19
    • 2013-05-25
    • 2010-10-12
    • 2011-04-30
    • 2022-12-15
    相关资源
    最近更新 更多