NodeJS安全设计:好吃的草莓味糖果,只给好朋友小红

上一篇文章中,我们已经建立了一个有缓冲机制的文件服务器,能给客户端响应附件类型的文件,其实,就爱莲(iLinkIT)而言,NodeJS的模块做到这样也就已经可以了,因为使用的场景就是电脑和手机之间,与部署在Internet上的服务器相比,安全性的要求是不高的。但是,我们这一系列文章的主要目的是学习,整到现在,我们只讲了服务器对客户端的响应,调用了response对象,但是对于客户端提交上来的请求(request对象),没有怎么关注过。本文就给服务器增加一点安全特性,服务器仅仅对特定的请求才响应,返回共享的文件。如爱莲(iLinkIT)的最终效果一样,只有扫描指定的二维码,才能实现文件的下载。

老规矩,先上一给图:

现在我们就来实现这样的功能,当服务器发现客户端的请求url是:http://localhost:8000/xiaohong时,就给客户端响应共享的文件,其他的请求任务,则给客户端反馈 Hello, iLinkIT。

代码如下:

 1 var http = require( 'http' );
 2 var fs = require('fs');
 3 var url = require( 'url' );
 4 
 5 var file_path = "D:\\ilinkit_logo.png" ;
 6 var file_stream ;
 7 var buffer_box = [] ;
 8 var file_length = 0 ; 
 9 
10 var file_name = file_path.substr( file_path.lastIndexOf('\\')+1 );
11 
12 fs.stat( file_path , function ( err , stat ){
13             if (err) {
14                 if ('ENOENT' == err.code) {
15                     console.log( 'File does not exist...' );
16                 } else {
17                     console.log( 'Read file exception...' );
18                 }
19             } else {
20                 file_stream = fs.createReadStream( file_path );      
21                 file_stream.on( 'data' , function( chunk ){
22                     buffer_box.push( chunk ) ;
23                     file_length += chunk.length ;
24                 } ); 
25                 file_stream.on( 'end' , function(  ){
26                     console.log( "文件读取完毕" );
27                 } );
28                 file_stream.on('error', function(err){
29                     console.log( "文件读取失败!" );
30                 }); 
31                 
32                 var server =http.createServer( function ( request ,response ){
33                   var h_path = url.parse( request.url ).pathname ;
34                   if( h_path === '/xiaohong' ){
35                     response.setHeader( 'Content-Type' , 'application/octet-stream' );
36                     response.setHeader( 'Content-Disposition' , 'attachment; filename=' + encodeURIComponent(file_name) );
37                     
38                     for( var buffer_index = 0 ; buffer_index<buffer_box.length ; buffer_index++ )
39                     {
40                         response.write( buffer_box[buffer_index] );
41                     }
42                     response.end();
43                    }
44                    else{
45                     response.end( 'Hello, iLinkIT' );    
46                    }
47                    
48                 } );
49                 server.listen( 8000 );
50                 console.log( 'HTTP服务器启动中,端口:8000.....' );
51                 
52             }//end else,读取文件没有发生错误
53 });                 

关键代码解析如下:

第3行,因为我们要解析客户端的请求,所以,需要加载url模块。

第33行,通过url.parse,解析出request对象中的请求路径部分。

第34行~第46行,整体逻辑是,如果第33行解析出的路径部分内容是“/xiaohong”,则给客户端响应指定的文件,如果不是“/xiaohong”,就打一个招呼,响应'Hello, iLinkIT'。

 

验证方式如下:

1. 启动服务器:打开命令行,进入js脚本所在的位置,执行:node g_ilinkit_1.js

2. 打开浏览器,输入:http://localhost:8000,显示如下:

因为请求的路径不是/xiaohong,所以显示的是Hello,iLinkIT的内容。

3. 打开浏览器,输入:http://localhost:8000/xiaohong,服务器反馈一个共享的文件附件,如下图所示。

 

今天的文章比较简单,就简单回顾一下:

在HTTP服务器的响应函数中,从request对象中可以获得客户端请求的主机名称、端口号以及请求路径等等信息,而核心模块url则提供了多种方法来解析请求中的url。

在爱莲(iLinkIT)真实的实现中,是会生成一个时间戳作为代码,服务器根据传入的时间戳参数决定如何响应,同时根据时间戳生成一个url地址的二维码。

 request对象是一个非常重要的对象,我们知道,在Web服务器中,请求的URL路径不同,服务器的响应也不同,这个是Web服务器的基本框架。如果用NodeJS搭建Web服务器,也是同样的道理,不过,托NodeJS社区的洪福,现在已经有很多现成的框架可以选用,比如:express 框架。在express框架中,基本的思路就是服务器根据request的url地址,根据设定的‘路由规则’来调用请求的处理模块,‘路由规则’和我们在Java Servlet中将一个url模式映射给一个servlet处理类似。而对客户端的响应中,服务器采用了“模板+数据”的方式,即根据业务诉求,从后台(例如:数据库)取得数据之后,填充到模板中,然后将页面反馈给客户端。当然,express框架也实现了如何进行身份识别等功能。如果你整明白了express框架,那么,你会对MVC(数据-视图-控制)架构模式会有更深刻的认识。

本系列文章的主题是围绕爱莲(iLinkIT)来开展的,所以,如果你要用NodeJS搞Web服务器,建议找专门介绍express框架的书看一看。

最后,感谢诸位的捧场,希望能多提宝贵意见,谢谢^_^~~

 

-----------------------爱莲(iLinkIT)系列文章------------------------------------------

 缘起爱莲:我要的,现在就要!

爱莲(iLinkIT)的架构与原理

遇见NodeJS:JavaScript的贵人

NodeJS服务器:一行代码 = 一个的HTTP服务器

NodeJS文件读取:感恩常在--抓把糖果,愉悦客人

NodeJS缓存机制:畅销货,就多囤一点呗

NodeJS安全设计:好吃的草莓味糖果,只给好朋友小红

NodeJS服务器退出:完成任务,优雅退出

 

posted @ 2015-11-27 21:13  阿来之家  阅读(608)  评论(0编辑  收藏  举报