1. 程式人生 > >node.js通過許可權驗證連線MongoDB

node.js通過許可權驗證連線MongoDB

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資料庫中通過db.createUser建立一個名稱為wopelo,密碼也與admin中wopelo相同的使用者出來,這樣子我們就可以連線testDB資料庫了。
當然,上面這個栗子是連線資料庫最原始的做法,我們有其他的方式進行連線與許可權認證,如果之後有機會我會和大家分享。