保护 Node.js 中的 API 路由
Posted
技术标签:
【中文标题】保护 Node.js 中的 API 路由【英文标题】:Protect API routes in Node.js 【发布时间】: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 路由。我在需要用户身份验证的地方使用令牌。 【参考方案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)
【讨论】:
以上是关于保护 Node.js 中的 API 路由的主要内容,如果未能解决你的问题,请参考以下文章
httpOnly cookie 中的 JWT - AuthGuard 和受保护的路由(Node.js、Angular)