NODEJS項目實踐0.4 [domain,pm2,log4js,md5]

1、前言

⋅⋅⋅上節咱們基於mongo數據存取的操做,實現了用戶註冊、登陸、退出功能,並應用了初級的權限驗證。本節將處理nodejs異常狀況、加密、日誌及進程守護。javascript

git : https://github.com/xiaolulu/mynodejs.git

二 、MD5

⋅⋅⋅密碼做爲用戶登陸惟一憑證,其安全性不言而喻,前面咱們的密碼操做存在兩個問題java

⋅⋅⋅a、用戶登陸及註冊都使用了明文密碼node

⋅⋅⋅b、數據庫保存了用戶的明文密碼git

⋅⋅⋅常規可使用二次加密,即前臺傳遞到後臺的密碼先加密一次,後臺再加密一次後存入數據庫。github

一、客戶端加密

⋅⋅⋅下載 md5.js 文件,用require包下。能夠到個人git上下載,也是網上找的,加了requireweb

⋅⋅⋅該文件較穩定且與業務無關,咱們放到 root/static/core/js內ajax

⋅⋅⋅在root/static/module/issue/register.js裏引用,在password傳輸前對其加密sql

javascriptrequire.config({
    baseUrl: basePath,
    paths: {
        all: 'public/js/all',
        md5: 'core/js/md5'  //引用md5
    }
})

define( ['md5','all'], function( md5 ){
    $( '#registerForm' ).on( 'submit', function(){
        var data = {
            username: $('#username').val(),
            password: md5.hex_md5( $('#password').val() ),  //對password加密
            email: $('#email').val()  
        }
    $.ajax
    ...
    })
});

⋅⋅⋅此時經過mongo終端能夠看到新註冊的密碼已經變成32的加密字段如數據庫

⋅⋅⋅123456 → 'e10adc3949ba59abbe56e057f20f883e'npm

二、服務器端加密

⋅⋅⋅在添加註冊數據到數據庫的時候,再加密一次

⋅⋅⋅nodejs包裝的加密模塊爲 crypto,經過package.json安裝

⋅⋅⋅對用戶數據存取都在root/web/controls/user.js,咱們對其修改

javascriptvar db = require( '../db/sql' ),
crypto = require( 'crypto' );       //引入  crypto 模塊
var md5 = function(data) {  //定義加密函數

    return crypto.createHash('md5').update(data).digest('hex').toLowerCase();  

} 
function addUser( req, res ){
    var data = req.body;
    data.password = md5( data.password );   //對存入的密碼加密
    ...
}

function findUser( req, res ){
    var data = req.body;
    data.password = md5( data.password );   //對查詢的密碼加密
    ...
}
...

⋅⋅⋅此時咱們再看數據庫裏的一樣的密碼,變化爲另一種32位的密文

⋅⋅⋅如 123456 → '14e1b600b1fd579f47433b88e8d85291'

⋅⋅⋅再執行一次註冊 / 登陸,功能是一樣可用的,但密碼已是安全的了。

⋅⋅⋅此時咱們完成了加密,之因此二次加密是由於,客戶端加密防止在向服務器傳送的過程當中被攔截,服務器再加密是防止內部出錯。

三 、nodejs異常處理

⋅⋅⋅開發程序不免會出現代碼異常,前臺js狀況還好些,一般隻影響當前用戶的當前頁面,但服務器若是出現異常,則要嚴重的多,處理不慎會形成整個項目的崩潰,中止服務,因此後臺的異常處理要很是全面。

⋅⋅⋅js出提供了異常處理機制,就是咱們經常使用的try{}catch(e){},nodejs也可使用

一、同步異常處理

⋅⋅⋅編輯 root/web/routes/index.js,app.use是全部請求的入口,對其作下包裝便可,在第二步中展現

二、異步異常處理

⋅⋅⋅nodejs最主要的優點在於其非阻塞的IO機制,意味着其內有大量的異步回調,這裏的錯誤是難以捕捉和處理的,也是try..catch所沒法達到的,nodejs提供了domain方法,一樣在 app.use裏作處理

javascript…
var domain  = require( 'domain' );  //引入domain
var Domain = domain.create();

Domain.on( 'error', function( e ){  //監聽異步錯誤
    console.log( 'error ' + e) 
});
…
app.use( function( req, res, next){ 
        try{
            if( privilege[ req.path ] && req.path != '/login' && !req.session.status ){
                if( req.method == 'GET' ){
                    res.redirect('/login');
                    } else {
                        res.send( { code: 1001, msg: 'need you to log in'})    
                    }           
            } else {
            Domain.run( function(){
                next(); //包裝異步處理,這樣回調出錯,也不會形成項目崩潰
            });
            }
        } catch( e ){
            res.redirect( '/' );
        }   

    });

4、pm2

⋅⋅⋅在上一步咱們作了異常處理,能夠減小項目崩潰的機率,但其仍是不夠穩妥,下面咱們使用進程守護模塊。

⋅⋅⋅pm2及forever模塊是目前較經常使用的nodejs進程守護模塊,前者更經常使用些、功能也更強大(提供負載)。其原理主要是pm2開啓一個主進程,另行再開子進程運行nodejs項目,主進程監聽子進程,若子進程崩潰,pm2會自行將其啓動,而且也能夠對一個項目啓動多個子進程,pm2主進程作隨機轉發請求。

一、安裝 npm install pm2 -g

⋅⋅⋅其相似於前面咱們安裝的node-dev,是用於啓動項目的,因此要安裝在全局

二、經常使用命令

javascriptpm2 start app.js    //啓動
    pm2 ls          //顯示已啓動的項目進程,會顯示項目id / name 負載等信息
    pm2 start app.js -i max //自動依賴電腦內核數,儘可能啓動多的進程
    pm2 reload all  //從新加載
    pm2 restart [ app_name | id | all ] //重啓項目,用於改了nodejs代碼時,其不具有node-dev功能
    pm2 stop  [ app_name | id | all ]   //中止某進程
    pm2 logs

5、log4js

⋅⋅⋅後臺項目日誌是極其重要的,後端不是客戶端 js那麼明晰,錯誤能夠隨時debug,日誌是很好的記錄,其對全部數據的請求進行記錄,也記錄了出現危害項目的行爲,如修改、刪除數據操做。

⋅⋅⋅咱們使用log4js模塊,經過package.json安裝

⋅⋅⋅在root/web下新建log文件夾存放日誌文件

⋅⋅⋅log4js仍是須要一些簡單的配置,前面使用md5及後面會到諸如ip獲取等也須要一些簡單的配置,咱們將這些簡單的不須要單獨成一個文件的配置都放是一個文件裏,新建 root/web/tool/gadget.js,添加代碼以下

javascriptvar log4js = require( 'log4js' );
    //引入log4js

var logConfig = {
    //設置配置項
    "appenders":[
        {"type": "console","category":"console"},
        {
            "type": "dateFile",
            "filename":"./log/",
    //目錄
            "pattern":"yyyyMMdd.log",
    //命名規則,咱們是按天,也能夠設置爲yyyyMMddhh.log,爲按時
            "absolute":true,
            "alwaysIncludePattern":true,
            "category":"logInfo"
        }
    ],
    "levels":{"logInfo":"DEBUG"}
}

log4js.configure( logConfig );
var logInfo = log4js.getLogger('logInfo');

module.exports = {
    logInfo: logInfo
}

⋅⋅⋅咱們對全部的請求做記錄,在root/web/routes/index.js,裏的app.use處添加日誌記錄

javascriptvar gadget = require( '../tool/gadget' );
….
app.use( function( req, res, next){ 
        console.log( req.path );  
        gadget.logInfo.info( req.path );
    //添加日誌,記錄全部請求路徑
        try{
            if( privilege[ req.path ] && req.path != '/login' && !req.session.status ){
                console.log( req.session.status );
                if( req.method == 'GET' ){
                    res.redirect('/login');
                    } else {
                        res.send( { code: 1001, msg: 'need you to log in'})    
                    }           
            } else {    
                Domain.run( function(){
                     next();
                });
            }
        } catch( e ){
            gadget.logInfo.error( req.path );
    //添加日誌,記錄出錯信息
            res.redirect( '/' );
        }   

    })

⋅⋅⋅項目啓動後,能夠看到root/web/log下自動新增了 20150723.log文檔,具體文件名視當前日期而定。

⋅⋅⋅訪問咱們的站點的任一個頁面,日誌文件中都會自動多出相應的記錄。

⋅⋅⋅實時查看文檔Linux下可用 tail -f 20150723.log,終端其會自動刷新目錄數據。

⋅⋅⋅本頁的 Domain.on( 'error' )回調裏也添加logInfo.error。還有DB的存取等因此有意義的數據往返及操做均可以記錄下來

6、總結

⋅⋅⋅本節咱們主要是對nodejs模塊的應用,處理異常( domain)、加密了數據(md5)、設置進程守護(pm2) 並 作了日誌記錄(log4js),每一塊只對基礎配置使用作了介紹,後面再單獨出一章詳細nodejs經常使用模塊

⋅⋅⋅近來工做較忙,就先寫到這裏,下節演示nodejs分紅先後臺兩部分接收頁面請求及DB存取、git操做

其它案例可參見: http://www.upopen.cn

全棧工程 - 技術新Q羣:435485569

相關文章
相關標籤/搜索