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)系列文章------------------------------------------