使用Node.js完成的第一個項目的實踐總結

http://blog.csdn.net/yanghua_kobe/article/details/17199417javascript


項目簡介

這是一個資產管理項目,主要的目的就是實現對資產的無紙化管理。經過爲每一個資產生成二維碼,來聯合移動終端完成對資產的審覈等。這個項目既提供了Web端的管理界面也提供移動端(Andorid)的資產審覈、派發等相關功能。
咱們用Node.js構建該項目的Web端以及移動端的Serveice API。
css

項目主框架:Express 簡介

Express 是一個很是流行的node.js的web框架。基於connect(node中間件框架)。提供了不少便於處理http請求等web開發相關的擴展。
Express簡單的結構圖:
html

Express的特性:前端

  • 基於Connect構建
  • 健壯的路由
  • 提供豐富的HTTP處理方法
  • 支持衆多視圖模板引擎(14+)
  • 內容協商
  • 專一於提供高性能
  • 環境基於配置
  • 快速構建可執行的應用程序
  • 高測試覆蓋率

前端框架簡介

Bootstrap

Bootstrap是Twitter推出的一個用於前端開發的開源工具包。它由Twitter的設計師MarkOtto和JacobThornton合做開發,是一個CSS/HTML框架。Bootstrap是簡潔、直觀、強悍的前端開發框架,讓web開發更迅速、簡單。
同時,不少基於Bootstrap的開源插件也讓Bootstrap社區更加活躍。
最新的Bootstrap3提供了很是強的定製化特性。包括Less,jQuery插件等。
Bootstrap 爲您提供了全部這些基本的模塊- Grid、Typography、Tables、Forms、Buttons和Responsiveness。
此外,還有大量其餘有用的前端組件,好比Dropdowns、Navigation、Modals、Typehead、Pagination、Carousal、Breadcrumb、Tab、Thumbnails、Headers等等。
有了這些,你能夠搭建一個Web 項目,並讓它運行地更快速更輕鬆。
此外,因爲整個框架是基於模塊的,你能夠經過定製你本身的CSS來使得它知足你的特殊需求。
它是基於幾種最佳實踐,咱們認爲這是一個很好的開始學習現代Web 開發的時機,一旦你掌握了HTML 和JavaScript/jQuery 的基本知識,你就能夠在Web 開發中運用這些知識。
java

Ember.js

Ember.js是一個JavaScript的MVC框架,它由Apple前僱員建立的SproutCore2.0更名進化而來。
構建一個Ember應用程序,一般會使用到六個主要部件:應用程序(Application)、模型(Model)、視圖(View)、模板(Template)、路由(Routing)和控制器(Controller)。
這裏咱們server端主要依賴express框架,它提供的這些功能跟express有些是相同的。咱們主要應用了Ember的模板組件,Express對於它提供了很好的集成。咱們只須要進行很簡單的配置便可:node

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.set('view engine''html');   
  2. app.set('views', path.join(__dirname, 'views'));  
  3. app.set("view options", {layout : false});  
  4. app.register('.html', require('ejs'));  

測試框架簡介

should.js

should 是用於node.js的一個表述性、可讀性很強的測試無關的「斷言」庫。它是BDD風格的,用一個單例的不可枚舉的屬性訪問器擴展了Object的prototype,容許你表述對象應該展現的行爲。
should的一個特性是能夠支持鏈式斷言,好比:mysql

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. user.should.be.an.instanceOf(Object).and.have.property('name''tj');  
  2. user.pets.should.be.instanceof(Array).and.have.lengthOf(4);  

mocha


Mocha是一個簡單、靈活、有趣的javascript測試框架。它能夠同時適用於node.js跟瀏覽器端。能夠很輕鬆得完成同步、異步測試,對產生異常的測試用例提供靈活以及準確的報告。能夠經過接口實現BDD、TDD、QUnit風格。

mocha + should.js


mocha是能夠實現BDD模式的測試框架,而should.js是BDD模式的斷言庫。把它們結合起來,能夠組建出一個很是靈活,而且不失表述性的測試框架。咱們全部給終端的接口,都基於它們完成了測試。

項目組件 - node modules

mysql

功能簡介:mysql- node.js平臺mysql驅動,支持事務、鏈接池、集羣、sql注入檢測、多作參數傳遞寫法等特性。
主頁地址:https://github.com/felixge/node-mysql
jquery

eventproxy

功能簡介:eventproxy- node.js 異步回調代理。主要用來解決node中深層次回調嵌套的問題,支持不少異步模式:多類型異步、重複異步、持續型異步。
主頁地址:https://github.com/JacksonTian/eventproxy
linux

validator

功能簡介:javascript的驗證工具集,支持兩種模式:check(校驗)/sanitize(處理),同時提供了可擴展的錯誤處理。
主頁地址:http://github.com/chriso/node-validator
c++

ejs

功能簡介:embered.jsjavascript 模板引擎(能夠跟express集成,做爲服務端模板引擎)
主頁地址:https://github.com/visionmedia/ejs

loader

功能簡介:loader- 資源加載工具,能夠區分開發模式、發佈模式;在發佈模式下可進行資源壓縮、合併。以實現減小靜態資源帶寬而且便於實現客戶端緩存
主頁地址:https://github.com/TBEDP/loader

canvas

功能簡介:canvas - node.js 經常使用的圖形圖像處理庫,是不少其它庫的基礎依賴庫
主頁地址:https://github.com/learnboost/node-canvas

captchagen

功能簡介:captchagen-node.js經常使用驗證碼圖片處理庫,依賴上面的canvas庫
主頁地址:http://github.com/wearefractal/captchagen

crypto-js

功能簡介:crypto-js- javascript 經常使用加密庫、hash庫封裝,支持sha-x / md5 / hash等各類加密、hash算法
主頁地址:http://github.com/wearefractal/captchagen

nodemailer

功能簡介:nodemailer- 郵件發送工具,支持SMTP等郵件發送協議
主頁地址:http://github.com/andris9/nodemailer

qrcode

功能簡介:qrcode- node.js服務端的qrcode生成器。支持多種輸出類型(dataUrl/file/bitArray)
主頁地址:http://github.com/soldair/node-qrcode

pdfkit

功能簡介:qrcode- node.js服務端的qrcode生成器。支持多種輸出類型(dataUrl/file/bitArray)
主頁地址:http://github.com/soldair/node-qrcode

excel

功能簡介:excel- node.js excel解析器,支持xlsx(Excel2007+)
主頁地址:https://github.com/trevordixon/excel

excel-export

功能簡介:excel-export- node.js excel生成器,支持導出excel
主頁地址:https://github.com/functionscope/Node-Excel-Export

net-ping

功能簡介:net-ping- node.js 對ping的封裝,用於測試目標主機是否可達
主頁地址:https://bitbucket.org/stephenwvickers/node-net-ping

debug

功能簡介:debug- node.js debug工具,對console.log的封裝,支持多種顏色輸出。
主頁地址:https://github.com/visionmedia/debug

項目組織結構



NPM - Node.js 模塊依賴管理工具

npm是管理node.js模塊依賴的工具,依賴於開源技術的優點就是你有很是多的優秀庫能夠幫助你快速構建一個系統,但就像一把雙刃劍,因爲開源致使版本的升級不可控。這時,一個集中性的模塊依賴管理工具的優點就十分明顯。它負責幫你管理開源項目的版本,你只須要添加對某個開源模塊的依賴便可。

unix/linux下安裝npm:

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. curl http://npmjs.org/install.sh | sudo sh  

如何在項目中使用npm管理你的依賴:

(1)在項目的根目錄下建立一個package.json文件

在dependencies下添加所須要依賴的模塊,示例以下:

打開terminal,進入項目的根目錄下:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. $ cd projectPath  
安裝這些module到本地repository:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. $ npm install   

這時你會發現,項目的根目錄下多了一個node_modules文件夾,那裏面就是從npm遠程庫裏下載的模塊而後「安裝」到你的項目中的。
如今,你就能夠在你的項目中應用你依賴的這些modules了。你能夠經過require關鍵字來使用他們。好比,

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. require("eventproxy");  

Node.js 模塊加載機制

node.js的模塊加載基於CommonJS規範。
在Node.js中,將模塊分爲兩大類:
(1)原生模塊
原生模塊在Node.js源代碼編譯的時候編譯進了二進制執行文件,加載速度最快。 
(2)文件模塊
node.js依賴modulepath(模塊路徑)來加載module,而modulepath的生成規則主要是從當前文件目錄開始查找node_modules文件夾,而後依次進入父目錄查找父目錄下的node_modules目錄直至到根目錄下得node_modules目錄。因此在require的時候,若是帶上module的路徑,則按照該路徑查找,若是沒有就按照上面的node_modules文件夾向上追溯查找,若是都沒有找到,則拋出異常。

自動化部署

項目環境的構建、部署都是自動化的。
咱們假設項目最終會發布在任意版本的Ubuntuserver上。在安裝git的前提下,經過以下命令去clone項目到本地:

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. git clone git://github.com/yanghua/FixedAssetManager_Server.git  
項目doc下有四個shell文件:
  • node_install_ubuntu.sh - 在ubuntuserver上安裝node.js的腳本
  • node-canvas-install_ubuntu.sh - 在Ubuntuserver上安裝node-canvas的腳本
  • mysql_install_ubuntu.sh - 在Ubuntu server上安裝mysql的腳本
  • dispatch.sh - 部署項目的腳本

將它們copy到當前用戶的home目錄下,依次執行便可。整個過程幾乎實現了無需人爲干涉的「自動化」。

pm2 - 線上監控管理工具


pm2是很是優秀工具,它提供對基於node.js的項目運行託管服務。它基於命令行界面,提供不少特性:
  1. 內置的負載均衡器(使用nodecluster module)
  2. 以守護進程運行
  3. 0s(不間斷)重啓
  4. 爲ubuntu/ CentOS 提供啓動腳本
  5. 關閉不穩定的進程(避免無限死循環)
  6. 基於控制檯監控
  7. HTTP API
  8. 遠程控制以及實時監控接口
pm2使用nodecluster構建一個內置的負載均衡器。部署多個app的實例來達到分流的目的以減輕單app處理的壓力。

異常監控與郵件推送


node.js 處處都是異步調用。經常使用的try/catch同步捕獲異常並處理的方式,在這裏不起做用了。這是由於不少callback已經離開了當時try的上下文,致使沒法獲取異常產生的堆棧信息。基於這個問題,咱們對異常處理的模式按類型進行區分處理:

(1)http請求異常
這種異常Express就能夠進行處理。若是是非法請求,在路由的時候,對未匹配的請求進行統一處理:

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.get("*", others.fourofour);   

(2)業務異常

這種異常一般不會影響到程序的運行,咱們以不一樣的異常代碼返回給前端或者終端,來給調用端友好的提示。

(3)應用程序級別的異常或必須處理的錯誤

這種狀況下,應用程序可能沒有辦法處理異常,也有可能由應用程序拋出。對於這種應用程序級別的異常。咱們用兩種方式來catch:

[1]利用Express提供的應用程序的異常處理機制:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.error(function(err, req, res, next) {                                             
  2.         mailServie.sendMail({                                                     
  3.           subject : "FixedAssetManager_Server[App Error]",                    
  4.           text    : err.message + "\n" + err.stack + "\n" + err.toString()            
  5.         });                                                                       
  6.         if (err instanceof PageNotFoundError) {                               
  7.             res.render("errors/404");                                             
  8.         } else if (err instanceof ServerError) {                                      
  9.             res.render("errors/500");                                             
  10.         }                                                                         
  11.     });  

[2]應用程序已經沒法響應處理了,則利用node.js提供的,對於進程級別的異常處理方式:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. process.on("uncaughtException"function (err) {                                      
  2.         mailServie.sendMail({                                                     
  3.             subject : "FixedAssetManager_Server[App Error]",                      
  4.             text    : err.message + "\n" + err.stack + "\n" + err.toString()          
  5.         });                                                                       
  6.     });   
這兩種應用程序級別的異常,優先級都比較高,所以咱們採用了郵件通知的策略,來輔助開發人員進行快速定位並修復。

靜態資源優化:壓縮合並與緩存

web應用中對於資源的定義大體分爲:靜態資源、動態資源兩種。動態資源一般是可變的,須要進行相應處理的,而靜態資源在線上一般都是不會變的。常見的靜態資源有:javascript文件、css文件、圖片文件等。對於這些靜態文件,咱們經過設置過時時間來進行緩存。而對於文本文件,因爲瀏覽器的解析行爲,對他們進行合併或者壓縮都不會產生影響。
這裏須要提到咱們在組件中介紹的Loader。在項目剛被clone下來的時候,須要先執行makebuild來對項目進行初始化。在初始化的過程當中,Loader會對項目的views文件夾中的文件進行掃描。它一般會掃描html界面:查找相似於以下的片斷:

[html]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <!-- style -->                                                                      
  2.     <%- Loader("/public/stylesheets/login.min.css")                            
  3.       .css("/public/libs/bootstrap/css/bootstrap.min.css")                        
  4.       .css("/public/stylesheets/login.css")                                       
  5.       .done(assets)                                                               
  6.       %>                                                                       
  7.     <!-- script -->                                                                 
  8.     <%- Loader("/public/libs/js/login.min.js")                                     
  9.       .js("/public/libs/jquery/jquery-1.10.2.min.js")                             
  10.       .js('/public/libs/bootstrap/js/bootstrap.min.js')                           
  11.       .js("/public/libs/CryptoJS_v3.1.2/rollups/sha256.js")                       
  12.       .js("/public/libs/js/login.js")                                                 
  13.       .done(assets)                                                               
  14.     %>  
去查找.css()以及.js()方法中的這些路徑參數,並對這些文件進行合併或壓縮混淆(這取決於配置),來產生一份assets.json(資產列表)文件。這裏面定義了一些鍵值對,鍵爲上面代碼段中Loader()方法後面跟的參數,值爲具體合併後文件的路徑。這樣,Loader會根據配置來判斷加載類型。若是當前爲開發模式或者爲debug模式,則調用.js()/.css(),基於其中的路徑參數來生成<script/> <link />。若是爲發佈模式,則根據.done()裏的assets鍵值對,結合Loader()的參數,來輸出合併後的文件。以減小前端http請求數量以及總大小。對publich文件夾下的文件,設置靜態文件緩存:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. //config for production env                                                       
  2. app.configure("production"function () {                                             
  3.     app.use('/public', express.static(staticDir, { maxAge: maxAge }));                
  4.     app.use(express.errorHandler());                                              
  5.     app.set('view cache'true);                                                      
  6. });  
由於設置了緩存,在從新改動這些靜態文件再發布的時候,若是緩存時間太長,則客戶端的靜態文件可能不會被替換。對於這個問題,Loader經過在文件的後綴追加一個版本號來做爲參數。這樣,當從新生成assets.json的時候每一個文件會產生新的版本號,瀏覽器會請求「新文件」替換掉客戶端老的緩存文件。

Restful風格的URL

Restful以「Resource」爲核心概念,認爲URL是用來表示一種資源。而不該該表示一個動做或者其餘的東西。而動做,好比「CRUD」正好對應http的四個method:get/post/put/delete。本項目中,咱們大部分的URL以Restful風格爲主,但沒有嚴格貫徹執行。

前端內容模板化、組件化

前端咱們採用的是ejs的模板來構建,它很好得實現了html的片斷化、組件化。有一個基礎的模板,別的都只是一塊html片斷。它們在服務端完成組合、解析,生成完整的html流輸出到客戶端。
這樣的開發模式,使得前端代碼的劃分比較清晰,組件化也使得代碼的複用變得更容易。

makefile

在項目初始化的過程當中,咱們使用makefile文件來使得一些動做自動化運行。好比咱們以前提到過的構建assets.json來合併文件的動做,就是經過執行makebuild文件來完成的。

加強的Debug模塊

目前,Node.js尚未很強大的調試工具。經常使用的輔助診斷方式就是打log。但繁多的日誌輸出,混雜在http log裏實在是不方便判斷。咱們在項目中使用了debug module來進行debug,他支持對log加不一樣顏色的key word而且還支持timestamp。你在一大堆日誌中,一眼就足以區分是從哪一個module或者組件輸出的。咱們在項目中對不一樣的layer應用不一樣的關鍵字:

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. var debug4Ctrller   = require("debug")("controller");  
  2. var debug4Proxy     = require("debug")("proxy");  
  3. var debug4Lib       = require("debug")("lib");  
  4. var debug4Test      = require("debug")("test");  
  5. var debug4Other     = require("debug")("other");  

將其置爲全局:

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. global.debugCtrller = debug4Ctrller;  
  2. global.debugProxy   = debug4Proxy;  
  3. global.debugLib     = debug4Lib;  
  4. global.debugTest    = debug4Test;  
  5. global.debugOther   = debug4Other;  
這樣你在controller層的log就能夠以以下方式log:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. debugCtrller("XXX %s""YYY");  

這樣在Terminal中,輸出的log會按照不一樣的顏色進行區分,辨別性明顯加強:




一切均可自動化——Grunt


Grunt是Javascript任務運行器。

爲何須要任務運行器?


對於須要反覆重複的任務,例如壓縮、編譯、單元測試、代碼檢查等,自動化工具能夠減輕你的勞動,簡化你的工做。

爲何使用Grunt?


Grunt 有龐大的生態圈,而且天天都在增加。你能夠自由地選擇數以百計的插件,幫助你自動化地處理任務。

用Grunt構建現有項目
1:全局安裝grunt命令行接口:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. npm install -g grunt-cli  

2:在項目的根目錄下新建一個Gruntfile.js文件,該文件爲grunt的配置、初始化文件
3:在packaget.json文件的devDependencies項中,添加grunt核心依賴以及須要的插件依賴:

注若是不想手動添加這些依賴,能夠直接打開Terminal,在項目根路徑下運行:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. npm install grunt --save-dev      

依賴會被自動寫入package.json的devDependencies項中。

關於Gruntfile的編寫規則,詳細請查看, Gruntjs中文文檔
目前項目中用到的幾個gruntplugin:
  • jshint: 用於對JS語法進行強制檢查
  • csslint: 用於對css語法進行強制檢查
  • uglify: 用於壓縮項目文件
Gruntfile配置的寫法很是靈活而且隨意,支持對文件進行正則匹配等特性。

統一的代碼風格


對於多人協做的項目,代碼風格顯得尤其重要。對於代碼風格的統一,咱們採用軟硬結合的方式。軟指的是自動化格式工具;硬指的是強制檢查工具。

自動格式化工具

目前項目中,兩人都採用SublimeText做爲代碼編輯器。藉助,SublimeText多如牛毛的插件,能夠簡化不少重複性工做,帶來顯著的效率提高。這裏介紹幾個格式化工具:
  • alignment:等號對齊排版插件
  • JSFormat:JS代碼格式化排版工具
  • HTML-CSS-JS Prettify 代碼格式化工具
對於2,3兩個插件,選擇他們的緣由是:他們開放了代碼風格的定義規則,而不是強制應用它們本身的規則。你能夠任意定義你想讓它格式化的代碼風格,好比:

你只須要在項目的根目錄下,建立一個.jsbeautifyrc文件,裏面對縮進,空格等進行定義便可覆蓋默認配置。這很是方便那些已經習慣了本身有一套代碼風格的人使用這些插件。

更難能難得的是,對於一個項目你能夠有多個.jsbeautifyrc文件進行配置。他們的優先級取決於這些配置文件靠近待格式化文件的程度(某種意義上就是這些配置文件在目錄層次的深度)。這很是切換咱們的需求:由於node項目先後端都是js。對於後端咱們採用的是4空格縮進,對於前端JS咱們採用的2空格縮進。那麼咱們只須要在前端JS文件夾下,新建一個新的.jsbeautifyrc配置文件,copy上面的配置,而後將indent_size修改成2便可。

強制檢查工具

自動格式化工具只是一種「效率工具」,不足以造成「強制規定」。這裏咱們輔以代碼檢查工具,來強制要求代碼風格、語法規範。

檢查工具在GruntSection已經列出,在commit代碼以前,必須運行檢查,並確保沒有任何Warnning跟Error。

Express 2.x to 3.x 接口適配與調整

一、ejs 服務端模板的調整:
原先的模板配置方式是採用在html文件,設置:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. <% layout('layout') -%>  

來標識一個component會套用某個模板,而在3.x中ejs模板引擎,改成採用middleware的方式使用:(須要安裝一個module:express-partials)
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.use(require('express-partials')());  

與此同時,3.x專門提供了一個設置引擎的接口:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.engine('html', require('ejs').renderFile);  

替代了原先2.x的:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.register('.html', require('ejs'));  

二、處理錯誤的方式改變:

2.x處理錯誤有專門的一個API:

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.error(function(err, req, res, next) {                                             
  2.     //error logic handle                                                      
  3. };  

3.x退而採用middleware的方式來處理:

[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. app.use(function(err, req, res, next) {                                           
  2.     //error logic handle                                                      
  3. }  

更多express2.x to 3.x的改變,能夠看看官方給出的 變動列表

從EventProxy 到 async 切換

eventproxy是淘寶前端團隊開發的一個node.js事件處理代理。用於輔助開放人員組織代碼的執行順序,對於不少須要干預執行順序與過程的代碼,避免了node.js深層嵌套的callback模式。

async跟eventproxy出於一樣的目的。但在API的設計模式上有所差別。async的API的風格偏向於「整合」,Eventproxy偏向於「拆分」。

Mongodb for node.js:mongoose的使用


model的定義

mongodb裏數據的集合稱之爲collection。而每一個collection都有一個schema與之對應,能夠簡單的理解爲是對其數據的定義(類型與結構)。

對應到mongoose裏,一個schema是一個model,形如:


好處:mongodb直接存儲了json文件,mongoose內部完成了對model數據對象的mapping,並自動繼承了一些基本操做接口。這樣的model是真正意義上的「充血模型」,而不是不少編譯型語音內構建的「貧血模型」式的model。

給每一個層定義索引文件


程序設計的一個重要指標:模塊性。在c/c++裏有頭文件,在面嚮對象語言裏有pagckage/namespace的概念。他們的目的之一就是提高模塊性,下降耦合度。

在node.js中,咱們也能夠採用相似c/c++的headfile的模式,以層爲單位。將對外可見的以文件爲單位的module以一個獨立的文件對外開放(一般咱們稱其爲index.js文件)。形如:


對於任何文件內的訪問權限跟可見性,咱們均可以採用exports關鍵字予以控制。

supertest 模擬 http request 測試

supertest是一個用於模擬http request的module,可藉助其進行web功能測試。

它提供了基於描述的API鏈式調用,能夠很是容易得模擬http請求測試,形如:


密碼採用混入salt值的方式進行加密

密碼只是採用hash方式進行「加密」,仍是至關不安全的。隨着如今計算能力的加強以及字典規模的擴大,簡單的md5已經很是不安全。一旦被拖庫,密碼很容易就會被破解。關於密碼的問題,除了採用(SSL加密數據傳輸鏈路)一直都沒有很是成熟的解決方案。因此,問題就退而求其次轉變爲如何提高破解難度的問題。而在密碼中混入salt,是一直很是經濟而有效的方式。這裏咱們處理用戶身份認證的方式是:

入庫以後的加密密碼 = sha3 (md5 (passwrod) + salt)

其中:salt的計算方式爲:sha256(userName)

解決linux解壓縮包中文亂碼


在windows上打包的zip壓縮包,在ubuntu上解壓縮後,凡是文件名含有中文的都出現了亂碼。產生這一問題的緣由是:在windows上壓縮文件,一般採用系統默認編碼(一般是gbk或gb2312),而傳到linux上去,在linux上一般都默認採用的utf8編碼,因此須要進行解碼。

項目中有須要在服務器上對上傳上來的zip壓縮包解壓縮的步驟,默認調用的是shell命令(unzip命令)。網上不少提供的解決方案是經過提供"-O"參數,顯示指定編碼。但未能成功,由於在如今版本的unzip裏,該參數已經失效了。經過unzip幾經折騰,仍是沒法解決亂碼問題,因而轉而採用7z來進行解壓縮,並顯式指定英文環境ASCII編碼(經過LANG=C),示例:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. LANG=C 7z e `source zip file path` -o`target path`    

其中參數「e」表示釋放全部文件到目標路徑(遞歸全部壓縮包中的子文件夾),參數「-O」指定解壓到的路徑(注意參數-O跟輸出路徑中間無空格)。

這一步只是完成了解壓,文件名這時仍是亂碼的。此時須要linux上專門的轉碼工具——convmv來進行編碼轉換!

若是該命令不存在,能夠先apt-getinstall一下,而後運行以下命令:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. convmv -f cp936 -t utf8 -r --notest -- `target path`/*  

該命令的意思是:對`targetpath`下的全部文件,從cp936編碼轉換成utf8編碼,其中的--notest表示不進行測試,直接轉換。若是你想確保轉碼安全,能夠先進行測試,看是否會產生亂碼,而後再進行轉碼,測試命令以下:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. convmv -f cp936 -t utf8 -r -- *  

這是你只要關注文件名是否會產生亂碼,無需關注目錄名,若是沒有亂碼,就能夠安全轉換了。

若是文件內容有亂碼,能夠藉助以下命令對文件進行轉碼:
[javascript]  view plain copy print ? 在CODE上查看代碼片 派生到個人代碼片
  1. iconv -f cp936 -t utf8 -o output.txt input.txt  

備註:我這邊遇到的是,在一個壓縮包內部有文件夾的狀況下,在windows壓縮,在ubuntu下解壓縮產生了中文亂碼。但若是隻是選中幾個文件直接壓縮,在ubuntu下不作轉碼,中文照常顯示。

源碼 & 總結 & TODO

因爲邊摸索邊構建,在代碼規範性上還有待進一步重構。同時,對 CNode官方社區的 開源代碼表示感謝,它真的讓咱們學到了許多。
本文所述項目開源在 github
相關文章
相關標籤/搜索