Nodejs学习笔记(五)--- Express构造web前篇

新建express项目,定义路由规则

1.创建一个项目express+ejs
cd 工作目录
express -e expressEjsWeb
cd expressEjsWeb && npm install
2.默认会有routes目录下会有index.js和users.js文件,这里为了不产生其它示例外的困扰,删除user.js文件
3.在app.js文件中修改代码

删除

var users = require('./routes/users');
...
app.use('/users', users);

添加

var subform = require('./routes/subform');
var usesession = require('./routes/usesession');
var usecookies = require('./routes/usecookies');
var usecrypto = require('./routes/usecrypto');            
...
app.use('/subform', subform);
app.use('/usesession', usesession);
app.use('/usecookies', usecookies);
app.use('/usecrypto', usecrypto);
image.png
4.在routes目录下添加subform.js、usesession.js、usecookies.js、usecrypto.js文件,并在对应的js文件中添加代码
//subform.js 代码
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('subform', { title: '提交表单及接收参数示例' });
});

module.exports = router;
//usesession.js 代码
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('usesession', { title: '使用session示例' });
});

module.exports = router;


//usecookies.js 代码
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  res.render('usecookies', { title: '使用cookies示例' });
});

module.exports = router;


//usecrypto.js 代码
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  res.render('usecrypto', { title: '加密字符串示例' });
});

module.exports = router;

5.在views目录下添加subform.ejs、usesession.ejs、usecookies.ejs、usecrypto.ejs文件,并在views目录下除了error.ejs外所有ejs文件中添加如下代码
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
    <a href="/">首页</a>     
    <a href="/subform">如何提交表单并接收参数?</a>
    <a href="/usesession">如何使用session?</a>
    <a href="/usecookies">如何使用cookies?</a>
    <a href="/usecrypto">如何字符串加密?</a>
  </body>
</html>
6.在app.js中添加3000端口监听并运行
app.listen(3000);

显示:

image.png
image.png

减少代码量,提取页面中的公共部分

1.在views目录下新建一个nav.ejs文件,并添加如下代码
<a href="/">首页</a>     
<a href="/subform">如何提交表单并接收参数?</a>
<a href="/usesession">如何使用session?</a>
<a href="/usecookies">如何使用cookies?</a>
<a href="/usecrypto">如何字符串加密?</a>

2.把views目录下index.ejs、subform.ejs、usesession.ejs、usecookies.ejs、usecrypto.ejs 中一样部分替换

 <% include nav %>
image.png

<% include 文件名 %> express提供include来嵌入其它页,这和html嵌入其它页类似

提交表单并接收参数Get,Post

构建一个表单简单模拟登录GET方式提交数据

1.打开subform.ejs文件,修改文件代码为如下:

image.png
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
     <% include nav %>
     <form>
          用户名:<input type="text" id="txtUserName" name="txtUserName" />
          密码:<input type="password" id="txtUserPwd" name="txtUserPwd" />
          <input type="submit" value="提交">
      </form>
  </body>
</html>

2.打开subform.js我们试着接收参数值并输出到控制台

image.png
//subform.js 代码
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
     console.log('get=====');
var userName = req.query.txtUserName;
var userPwd = req.query.txtUserPwd;
var userName2 = req.param('txtUserName');
var userPwd2 = req.param('txtUserPwd');

  console.log('req.query用户名:'+userName);
  console.log('req.query密码:'+userPwd);
  console.log('req.param用户名:'+userName2);
  console.log('req.param密码:'+userPwd2);
  res.render('subform', { title: '提交表单及接收参数GET' });
});

module.exports = router;

3.运行,并提交表单 在浏览器中运行:http://localhost:3000/subform

image.png

输入提交

image.png
image.png

控制台

image.png

完成GET方式提交表单!

构建一个表单简单模拟登录post方式提交数据

1.首先修改一下subform.ejs文件中的form标签:

<form method="post">
...
</form>

2.再在subform.js中添加代码,接收post提交、接收参数并输出到控制台

image.png
router.post('/', function(req, res) {
     console.log('post=====');
var userName = req.query.txtUserName;
var userPwd = req.query.txtUserPwd;
var userName3 = req.body.txtUserName;
var userPwd3 = req.body.txtUserPwd;
var userName2 = req.param('txtUserName');
var userPwd2 = req.param('txtUserPwd');

  console.log('req.query用户名:'+userName);
  console.log('req.query密码:'+userPwd);
  console.log('req.body:'+userName3);
  console.log('req.body:'+userPwd3);
  console.log('req.param用户名:'+userName2);
  console.log('req.param密码:'+userPwd2);
  res.render('subform', { title: '提交表单及接收参数POST' });
});

3.运行,并提交表单 在浏览器中运行:http://localhost:3000/subform,输入表单项并提交,可以发现url不会发生变化

image.png

控制台输出:

image.png

完成POST方式提交表单!

总结:
req.query:我用来接收GET方式提交参数
req.body:我用来接收POST提交的参数
req.params:两种都能接收到

req.body,Express处理这个post请求是通过中间件bodyParser,可以自行找下API

密码字符串加密

当我们提交表单后,比如密码这些敏感信息,Node.js提供了一个加密模块
Crypto http://nodejs.org/api/crypto.html
1.usecrypto.js,修改代码:

image.png
var express = require('express');
var router = express.Router();
var crypto = require('crypto');

/* GET home page. */
router.get('/', function(req, res) {
  
  res.render('usecrypto', { title: '加密字符串示例' });
 
});

router.post('/',function(req, res){
  var 
  userName = req.body.txtUserName,
  userPwd = req.body.txtUserPwd;

  //生成口令的散列值
  var md5 = crypto.createHash('md5');   //crypto模块功能是加密并生成各种散列
  var en_upwd = md5.update(userPwd).digest('hex');

  console.log('加密后的密码:'+en_upwd);
  
  res.render('usecrypto', { title: '加密字符串示例' });
});

module.exports = router;

2.usecrypto.ejs,修改代码

image.png
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>     
      <% include nav %>

      <form method="post">
          用户名:<input type="text" id="txtUserName" name="txtUserName" />
          密码:<input type="password" id="txtUserPwd" name="txtUserPwd" />
          <input type="submit" value="提交">
      </form>
  </body>
</html>

3.运行,提交表单,查看控件台输出

image.png

成功MD5方式加密!
  其中用到了createHash(algorithm)方法 ,这是利用给定的算法生成hash对象
  update(data, [input_encoding])方法,可以通过指定的input_encoding和传入的data数据更新hash对象,input_encoding为可选参数,没有传入则作为buffer处理 (input_encoding可为'utf-8'、'ascii'等)
  digest([encoding])方法,计算数据的hash摘要值,encoding是可选参数,不传则返回buffer (encoding可为 'hex'、'base64'等);当调用digest方法后hash对象将不可用;

具体参考:Crypto http://nodejs.org/api/crypto.html

session的使用

express中可以用中间件来使用session,express-session( https://github.com/expressjs/session ) 可以存在内存中,也可以存在mongodb、redis等中...
  更多中间件:https://github.com/senchalabs/connect#middleware

示例设计思路:使用两个页面,一个登录,两个页都判断是否有这个session,如果有,显示已登录,没有则显示一个登录按钮,点此按钮,记录session

1.首先通过npm安装这个中间件,打开package.json文件,在dependencies节点下添加一个键值对 "express-session" : "latest"
image.png
"dependencies": {
    ...,
    "express-session" : "latest" 
  }
2. cd到项目根目录下,执行npm install
image.png
3.app.js,添加代码
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
...      
//这里传入了一个密钥加session id
app.use(cookieParser('Tiany'));
//使用靠就这个中间件
app.use(session({ secret: 'tiany'}));
...
image.png
4.usesession和usecookies,修改ejs和js如下

usesession.ejs和usecookies.ejs

image.png

usesession.js

//usession.js 示例代码
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  
  if(req.session.islogin)
  {
       console.log('usesession:' + req.session.islogin);
     res.locals.islogin = req.session.islogin;      
  }

  res.render('usesession', { title: '使用session示例' });
});

router.post('/', function(req, res) {
  
  req.session.islogin = 'success';
  res.locals.islogin = req.session.islogin;

  res.render('usesession', { title: '使用session示例' });
});

module.exports = router;

usecookies.js

//usecookies.js 示例代码

var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {

  if(req.session.islogin)
  {
      console.log('usecookies:' + req.session.islogin);
    res.locals.islogin = req.session.islogin;      
  }

  res.render('usecookies', { title: '使用cookies示例' });
});

router.post('/', function(req, res) {
  
  req.session.islogin = 'success';
  res.locals.islogin = req.session.islogin;

  res.render('usecookies', { title: '使用cookies示例' });
});

module.exports = router;
5.运行并查看
image.png
image.png
6.点击登录按钮后,再查看这两个页
image.png
image.png
7.关闭浏览器,再打开查看这两个页

这是新开的,显示也是已登录

image.png
image.png

官方示例:https://github.com/visionmedia/express/blob/master/examples/session/index.js

cookies

如果是登录,那常见就是“记录密码”或“自动登录”功能,这个一般用 cookies来完成
cookies存在客户端,安全性较低,一般要存入加密后的信息;建议要设置使用过期时间或不使用时删除掉
express也同样可以用中间件来使用:https://github.com/expressjs/cookie-parser

1.修改下usecookies.js

image.png
//usecookies.js 示例代码
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
   
  if(req.cookies.islogin)
  { 
       console.log('usecookies-cookies:' + req.cookies.islogin);
       req.session.islogin = req.cookies.islogin;
  }  
  
  if(req.session.islogin)
  {
      console.log('usecookies:' + req.session.islogin);
    res.locals.islogin = req.session.islogin;      
  }

  res.render('usecookies', { title: '使用cookies示例' });
});

router.post('/', function(req, res) {
  
  req.session.islogin = 'success';
  res.locals.islogin = req.session.islogin;
  //maxAge为过期时长,毫秒为单位,我设置一分钟
  res.cookie('islogin', 'sucess', { maxAge: 60000 });

  res.render('usecookies', { title: '使用cookies示例' });
});

module.exports = router;

2.运行访问 http://localhost:8000/usecookies,点击登录按钮登录成功并记录cookies
maxAge为过期时长,毫秒为单位,我设置一分钟
3.关闭浏览器,再次访问http://localhost:8000/usecookies ,页面显示已登录
4.再次关闭浏览器,过一分钟再访问http://localhost:8000/usecookies,页面不再是已登录,而是显示登录按钮,表示cookies过期,不会自动登录

官方示例:https://github.com/visionmedia/express/blob/master/examples/cookies/app.js

清除session和cookies

//清除cookies
res.clearCookie('islogin');
  
//清除session
req.session.destroy();
小结一下:
cookie

在web应用中,多个请求之间共享“用户会话”是非常必要的。但HTTP1.0协议是无状态的。那这时Cookie就出现了。那Cookie又是如何处理的呢?
Cookie的处理:
服务端向客户端发送Cookie
客户端的浏览器把Cookie保存
然后在每次请求浏览器都会将Cookie发送到服务端

在HTML文档被发送之前,Web服务器通过传送HTTP 包头中的Set-Cookie 消息把一个cookie 发送到用户的浏览器中,如下示例:
Set-Cookie: name=value; Path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT;

其中比较重要的属性:
name=value:键值对,可以设置要保存的 Key/Value,注意这里的 name 不能和其他属性项的名字一样
Expires: 过期时间(秒),在设置的某个时间点后该 Cookie 就会失效,如 expires=Wednesday, 09-Nov-99 23:12:40 GMT
maxAge: 最大失效时间(毫秒),设置在多少后失效
secure: 当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效
Path: 表示 cookie 影响到的路,如 path=/。如果路径不能匹配时,浏览器则不发送这个Cookie

session

session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而session保存在服务器上。
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么session机制就是通过检查服务器上的“客户明细表”来确认客户身份。
session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

两者的区别:

cookie数据存放在客户的浏览器上,session数据放在服务器上。
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session。
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能 考虑到减轻服务器性能方面,应当使用COOKIE。
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
所以建议:将登陆信息等重要信息存放为session、其他信息如果需要保留,可以放在cookie中

其他一些session,cookie 配置
http://www.cnblogs.com/vipzhou/p/4949120.html

大多是网上和书籍的内容简单的跑了下,这篇写的比较糙,还有许多值得考虑的,以后慢慢思考。有建议还请提出来,谢谢。

ps:在搭建中存在的一个破问题。。。

在使用session的时候报错了:
Cannot read property 'islogin' of undefined

TypeError: Cannot read property 'islogin' of undefined
at D:\Program Files\nodejs\WebstormProjects\SecondTest\routes\usesession.js:10:19
at Layer.handle [as handle_request] (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\layer.js:95:5)
at next (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\route.js:131:13)
at Route.dispatch (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\layer.js:95:5)
at D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\index.js:277:22
at Function.process_params (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\index.js:330:12)
at next (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\index.js:271:10)
at Function.handle (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\index.js:176:3)
at router (D:\Program Files\nodejs\WebstormProjects\SecondTest\node_modules\express\lib\router\index.js:46:12)

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容