node.js通过权限验证连接MongoDB

来源:互联网 发布:java时间戳转换为date 编辑:程序博客网 时间:2024/04/29 09:29

2017年1月,大部分mongodb由于配置的疏忽给了黑客可乘之机,于是便发生了一系列的杯具。所谓的配置疏忽其实就是mongdb所有者没有为mongodb开启权限认证,导致数据库“在任何网络环境,不使用账号直接登录”。这件事情告诉我们——做人不能太懒,虽然有时密码设置了和没设置一样,但该设置的密码还是要设置的。。。。那么我们应该如何为mongodb开启权限认证呢?开启权限认证之后又如何通过node.js进行连接呢?
首先在命令行中进入到mongodb的bin目录,连接数据库

mongo --port 27017

这里写图片描述
由于我现在已经开启了权限,输出没有任何问题,但如果你没有开启权限认证,就会出现警告,不信你可以试一下。
为mongodb添加用户的方法如下

db.createUser({    user:"用户名",    pwd:"密码",    customData:"对这个账户的描述",    roles:[{role:"角色类型",db:"角色创建在哪个数据库上"},{role:"角色类型",db:"角色创建在哪个数据库上"},.....]})

这里大家需要注意,roles参数的值是一个数组,角色的类型分为数据库角色(read/readWrite/dbAdmin/dbOwner/userAdmin)、集群角色(clusterAdmin等)、备份角色(backup等)、其他特殊角色四大类,root作为超级管理员角色我不知道该归到哪一类中,所以就把它单独拿出来吧。
如果我们在mongodb的命令行中使用show dbs的话,会发现一个admin数据库,如果我们在这个数据库里创建用户,那么该用户可以在所有数据库中使用ta的权限,比如读写,这就是传说中的全局认证。
我们现在admin库里建立一个名为wopelo的用户,虽然我们创建了一个用户,但如果我们再次登录mongodb还是不需要认证就可以访问,这是因为我们只是创建了用户而没有开启权限认证。需要注意的是mongodb默认不需要认证就可以访问,一旦开启认证,就需要用户名与密码才可登录,所以在我们第一次创建用户时一定要先创建用户再开启权限认证。
开启权限认证需要我们编辑mongod.conf文件(某些电脑上没有该文件,取而代之是mongod.config),在文件最后添加 auth=true
这里写图片描述
保存之后我们再次进入到mongodb,发现还是不需要认证,不过你可以随便运行一个指令(除开use命令),命令行都会提示出错,原因是权限不够
这里写图片描述
那么应该如何认证呢?我们在创建用户时设置了roles的db字段,此时我们进入到对应的数据库中(所以在没有认证的情况下,use是为数不多可以用的命令),使用db.auth(“用户名”,”密码”)进行验证,结果为1就成功,为0则失败。
顺便提一下,如果想要查看全部用户,则应进入admin库,使用show users
通过上述操作,我们可以在命令行中进行权限验证,那么我们如何在node.js中通过权限访问数据库呢?
以一个最简单也最原始的例子

var http=require("http");var mongo=require("mongodb");var querystring=require("querystring");var nowPage;var server=new mongo.Server("localhost",27017,{auto_reconnect:true});var serverHttp=http.createServer();serverHttp.listen(1337,"127.0.0.1");serverHttp.on("listening",function(){    console.log("监听开始");});var db=new mongo.Db("testDB",server,{safe:true});serverHttp.on("request",function(req,res){    if(req.url!="/favicon.ico"){        console.log("收到客户端请求");        console.log("客户端请求方法:"+req.method+"\r\n");        req.on("data",function(data){            var iff=querystring.parse(decodeURIComponent(data));            console.log(iff);            if(iff.find){                Find(res);            }else if(iff.add){                Add(res,iff);            }else if(iff.updata){                upData(res,iff);            }else if(iff.remove){                Remove(res,iff);            }else if(iff.paging){                Page(res,iff);            }else if(iff.moving){                Moving(res,iff);            }        });        req.on("end",function(){            console.log("数据接收完毕");        });    }});db.on("close",function(err,db){    if(err){        console.log("关闭发生错误"+err);    }else{        console.log("关闭数据库成功");    }});function Find(x){    console.log("页面加载时显示数据");    db.open(function(err,db){        if(err){            console.log("连接发生错误:"+err);        }else{            console.log("连接数据库成功");            db.authenticate("wopelo","密码",function(){                db.collection("Collections",function(err,collection){                    collection.find({},{fields:{_id:0}}).toArray(function(err,docs){                        if(err){                            console.log("查询发生错误");                        }else{                            console.log("数据条数:"+docs.length);                            var totalPage=Math.ceil(docs.length/7);                            var totalMes=docs.length;                            docs=docs.slice(0,7);                            docs.push({"totalPage":totalPage});                            docs.push({"totalMes":totalMes});                            console.log(JSON.stringify(docs));                            x.statusCode=200;                            x.setHeader("Content-Type","text/plain");                            x.setHeader("Access-Control-Allow-Origin","http://localhost");                            x.write(JSON.stringify(docs));                            x.end();                            nowPage=1;                        }                        db.close();                    });                });            });        }    });}

上面的代码只是一个项目的一个片段而已,写的也不是很成熟,但需要注意其中的
db.authenticate(“wopelo”,”密码”,function(){}
这段代码就是在node.js中使用权限验证的关键。但需要给大家泼一盆冷水——这样子写你还是不能通过权限认证,那么这是为什么呢?前面我将“我们现在admin库里建立一个名为wopelo的用户”这句话加粗,原因就在这里。wopelo用户只是建立在admin库上的,虽然建立在admin库的用户可以进行全局认证,但前题是我们必须先use admin数据库进行认证才可以,而这里我们直接连接的testDB数据库,整个数据库中是没有名为wopelo的用户的,所以最好的解决方案就是在tesDB数据库中创建一个名称为wopelo,密码也与admin中wopelo相同的用户出来,这样子我们就可以连接testDB数据库了。
当然,上面这个栗子是连接数据库最原始的做法,我们有其他的方式进行连接与权限认证,如果之后有机会我会和大家分享。最后,还是那句老话,欢迎大家在下方评论区批评指正。

1 0