【问题标题】:Protect API routes in Node.js保护 Node.js 中的 API 路由
【发布时间】:2018-03-31 00:59:55
【问题描述】:

我的 Node.js API 中有一些路由将数据从 MongoDB 数据库发送到 Angular 4 前端。

例子:

Node.js 路由:

router.get('/api/articles', (req, res) => {
    Article.find({}, (err, articles) => {
        if(err) return res.status(500).send("Something went wrong");
        res.status(200).send(articles);
    });
});

Angular 4 服务功能:

getArticles() {
    return this.http.get('http://localhost:3000/api/articles')
    .map(res => res.json()).subscribe(res => this.articles = res);
}

问题是,如何保护我的 Node.js API 路由免受浏览器访问?当我去http://localhost:3000/api/articles时,我可以看到我所有的json格式的文章。

【问题讨论】:

  • 你真的不能。如果您要公开一个 API 以供 Angular 使用,那么任何 Web 代理也可以调用该 API。您可以在您的网站上要求一个登录帐户,您的服务器可以在 API 响应之前验证该帐户,但这就是您可以做的事情。可以设置各种障碍,使其更难从您的 Angular 代码外部访问,但与坚定的黑客相比,没有一个是安全的。
  • @jfriend00 谢谢,非常感谢您的 cmets。我的目标只是防止通过浏览器直接访问公共 API 路由。我在需要用户身份验证的地方使用令牌。

标签: javascript node.js mongodb angular


【解决方案1】:

这不是安全措施,只是过滤请求的一种方式。为了安全,请使用 JWT 或类似的其他机制。

如果 Angular 应用程序由您控制,则发送一个特殊的标头,例如 X-Requested-With:XMLHttpRequest(chrome 默认为 AJAX 调用发送它)并在响应之前检查此标头的存在。

如果您真的很想将端点暴露给特殊情况,请使用唯一标头 X-Request-App: MyNgApp 并对其进行过滤。

【讨论】:

  • 这是一种防止在浏览器中键入 URL 的简洁方法。没有做任何事情来阻止黑客使用 API(你基本上做不到)。
  • 绝对不是安全措施。这只是一个过滤器。
  • 我决定使用这个解决方案来处理公共内容。在需要用户身份验证的地方,我使用令牌作为安全措施。
【解决方案2】:

除非您愿意实施某种身份验证,否则您不能真正做到——即您的 Angular 用户将需要登录 api。

可以让它不那么方便。例如,简单地将您的路由切换为接受POST 请求而不是GET 请求将阻止浏览器轻易看到它。它仍然会在开发工具或 curl 中可见。

或者,您可以使用您在 express 处理程序中查找的 angular 请求设置一个标头,但这似乎只是为了安全的外观而做的很多工作。

【讨论】:

    【解决方案3】:

    最好的方法是实现一个认证令牌系统。您可以从静态令牌开始(稍后您可以通过授权实现动态令牌)。

    Token 只是一个字符串,用于确保请求经过身份验证。

    Node.js 路由:

    router.get('/api/articles', (req, res) => {
        let token = url.parse(req.url,true).query.token;   //Parse GET param from URL
        if("mytoken" == token){         // Validate Token
           Article.find({}, (err, articles) => {
            if(err) return res.status(500).send("Something went wrong");
            res.status(200).send(articles);
           });
        }else {
           res.status(401).send("Error:Invalid Token"); //Send Error message
        }
    
    });
    

    Angular 4 服务功能:

    getArticles() {
        return this.http.get('http://localhost:3000/api/articles?token=mytoken') // Add token when making call
        .map(res => res.json()).subscribe(res => this.articles = res);
    }
    

    【讨论】:

    • @mikebrsv - 值得理解的是,任何可以从浏览器 Javascript 中完成的事情(例如此处建议的内容)都可以由任何黑客完成,因此这只是一个障碍,而不是实际的预防措施。而且,这甚至不是防止用户在浏览器中输入 URL 的最简单方法——这可以通过将 API 更改为仅使用 POST 而不是 GET 来完成(这不符合 REST,但可以正常工作,因为所有来自 URL 栏的浏览器请求是 GET)。
    【解决方案4】:

    使用 Express,您可以使用路由处理程序来允许或拒绝访问您的端点。此方法由 Passport 身份验证中间件使用(顺便说一下,您可以使用它)。

    function isAccessGranted (req, res, next) {
      // Here your authorization logic (jwt, OAuth, custom connection logic...)
      if (!isGranted) return res.status(401).end()
      next()
    }
    
    router.get('/api/articles', isAccessGranted, (req, res) => {
      //...
    })
    

    或者让它对你的所有路线更通用:

    app.use('*', isAccessGranted)
    

    【讨论】:

      猜你喜欢
      • 2019-09-13
      • 2014-10-18
      • 2018-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-03
      • 2017-10-12
      • 2018-09-13
      相关资源
      最近更新 更多