简体   繁体   English

数据库公开:最佳实践

[英]Database Exposure: Best Practices

I'm a relatively new web programmer and I'm currently working on my first major project. 我是一个相对较新的Web程序员,目前正在从事我的第一个主要项目。 I'm using angular, express (on top of node), and the graph database neo4j. 我正在使用angular,express(在节点顶部)和图形数据库neo4j。 Right now I'm trying to determine the best (in terms of security and speed optimization) way to set up how the web app interacts with the database. 现在,我正在尝试确定最佳的方式(在安全性和速度优化方面)来设置Web应用程序与数据库的交互方式。

Right now I feel like I'm going into this somewhat blindly- What I'm looking for is a guide of best practices, security issues to take into account, and any other relevant advice or pitfalls to be aware of in setting up a web app backend. 现在,我觉得我有点盲目地进入这个过程-我正在寻找的是最佳做法指南,要考虑的安全性问题以及建立网络时需要注意的任何其他相关建议或陷阱应用后端。

To put this into a bit more concrete terms I'll give you an idea of how I'm setting up routes right now. 为了更具体地说明这一点,我将为您介绍一下我现在如何设置路线。 The following are the routes setup in the app.js file. 以下是app.js文件中的路由设置。

    //match database query functions
function dataQuery(req, res) {
    var func = database[req.param('query')];
    func(req, res);
}
    //match database create functions
function dataCreate(req, res) {
    var func = database[req.param('create')];
    func(req, res);
}
//handle data queries
app.get('/query/:query', dataQuery);

//handle adding new content
app.post('/create/:create', dataCreate)

Essentially I have it set up so that I POST or GET to a url that just goes and executes a function. 从本质上讲,我已经对其进行了设置,以便我将POST或GET传递到刚开始执行功能的URL。 I'm essentially naming the function I want to run in the url: /query/theNameOfTheFunction. 我实质上是在要在url中运行的函数命名:/ query / theNameOfTheFunction。 These functions then go and either build a cypher query (neo4j's query language) utilizing information in the request to interact with the database or handles things like adding user uploaded images. 然后,这些功能开始运行,或者利用请求中的信息来构建密码查询(neo4j的查询语言)以与数据库进行交互,或者处理诸如添加用户上传的图像之类的事情。

Example: Creating Content (URL: /query/createContent) 示例:创建内容(URL:/ query / createContent)

exports.createContent = function (req, res) {

    var content = JSON.parse(req.query.content);
    var query = ("CREATE (n:Content {Title: {title}, URL: {url}, Description: {description}, Source: {source}, Links: {links}, Value: {valueStatement} })");

    query = query.replace("{title}", "\"" + content.title + "\"");
    query = query.replace("{url}", "\"" + content.url + "\"");
    query = query.replace("{description}", "\"" + content.description + "\"");
    query = query.replace("{source}", "\"" + content.source + "\"");
    query = query.replace("{links}", "\"" + content.links + "\"");
    query = query.replace("{valueStatement}", "\"" + content.valueStatement + "\"");

   db.query(query, function (err, results) {
       if (err) {res.send()};
       res.send();
   });
}

Here I've got a template for the query and just drop in user generated information using replace. 在这里,我有一个查询模板,只是使用replace删除了用户生成的信息。

Example: Adding images to server (URL: /create/addImage) 示例:将图像添加到服务器(URL:/ create / addImage)

exports.addImage = function (req,res) {
    var url = req.query.url;
    var fileName = req.query.fileName;

    console.log(req.query);
    request(url).pipe(fs.createWriteStream("./img/submittedContent/" + fileName));
    res.send();
}

It seems that this approach is probably not very scalable but I'm not sure how to best organize the code on the server side. 看来这种方法可能不是很可扩展,但是我不确定如何最好地在服务器端组织代码。

One other specific example I would like to mention is the following case. 我要提及的另一个具体示例是以下情况。 The query itself is complicated and I've pushed creating it to the client side for now (the query looks for content related the terms that the user has selected and varies in length accordingly). 查询本身很复杂,我现在已经将其推到客户端(查询将查找与用户选择的术语相关的内容,并相应地更改长度)。 The client sends the query that is created it is passed into the neo4j api. 客户端发送创建的查询,并将其传递到neo4j api中。 Obviously there are concerns here- if the user is able to define the query they could perform any action on the database (deleting everything or whatever). 显然,这里存在问题-如果用户能够定义查询,那么他们可以对数据库执行任何操作(删除所有内容或其他内容)。 I'm not clear on how someone could go about doing this exactly, but it certainly seems feasible. 我尚不清楚有人可以如何准确地做到这一点,但是这似乎是可行的。

exports.getContent = function (req, res) {
    var query = req.query.query;

        //would checking for black/white list key terms be enough security? (remove, create, set, etc)

    db.query(query, function (err, results) {
        if (err) {throw err};
        res.send(results);
    });
}

Am I going about this stuff completely wrong headed? 我是否会完全错误地处理这些问题? I've never gotten a formal introduction to server side scripting and am only going off of things I've read. 我从来没有对服务器端脚本进行正式介绍,只是从我读过的东西中脱颖而出。 I would like to do it the 'right way' but I need to know what that way is first... 我想以“正确的方式”做到这一点,但我需要知道首先采用哪种方式...

Just some random pointers: 只是一些随机指针:

  • I would suggest setting up a RESTful web API to handle the communication between Angular and your database; 我建议设置一个RESTful Web API来处理Angular和您的数据库之间的通信。 it takes the hassle out of having to invent all the routes yourself and it also means you can use great libraries like Restangular (for the client) and Restify (for the server) to handle the communications; 它消除了您必须自己发明所有路由的麻烦,也意味着您可以使用诸如Restangular (对于客户端)和Restify (对于服务器)之类的出色库来处理通信。
  • not sure which Neo4j driver you're using, but I'm pretty sure they all support parameterized queries, meaning that you don't need to do all those query.replace() calls ( see ); 不知道您使用的是哪个Neo4j驱动程序,但是我很确定它们都支持参数化查询,这意味着您不需要执行所有这些query.replace()调用( 请参阅 query.replace() );
  • depending on the number of images that might get uploaded, storing them in the filesystem might be okay, although you should never trust the passed filename; 根据您可能上传的图像数量,可以将它们存储在文件系统中,尽管您永远不应该信任传递的文件名; if you want a bit more scalability, you could consider using MongoDB's GridFS ; 如果您想要更多的可伸缩性,可以考虑使用MongoDB的GridFS
  • never trust queries being passed from the client to be performed on the server; 从不信任从客户端传递来的查询,以在服务器上执行; if you can build the query on the client side, you can also build it on the server side with information passed from the client to the server (again, use parameterized queries); 如果可以在客户端上构建查询,那么还可以使用从客户端传递到服务器的信息在服务器端上构建查询(再次使用参数化查询);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM