1. 程式人生 > >node.js學習筆記(9)--使用cookie與session保持登入

node.js學習筆記(9)--使用cookie與session保持登入

我們來做一個使用cookie和seesion保持網站持久登入的例子,來讓我們瞭解在node是如何使用他們的

1.初始化專案

我們使用express專案生成器生成一個專案:
$express -e cookie
$cd cookie 
$npm install

使用cookie需要 cookie-parser中介軟體,我們的express生成的專案中已經幫我們配置好了。

2.新增頁面

專案建立好之後,開啟views資料夾 建立login.ejs頁面,以及修改index.ejs頁面。

登入頁面: login.ejs
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title登入</title>
    <style>
        p{color: red}
    </style>
</head>
<body>
    <form action="login" method="post">
        <%if(typeof(error) !== 'undefined' && error){%>
         <p><%= error %></p>
        <% } %>
         使用者名稱:<input type="text" name="username" ><br/>
         密碼:<input type="password" name="pwd" ><br/>
        <input type="submit" value="登入">
    </form>
</body>
</html>
其中我們通過error來處理錯誤顯示。注意:不能直接判斷error是否存在,因為當error為undefined時候會報錯,我們需要通過typeof來檢測一下。 主頁面: index.ejs
<!DOCTYPE html>
<html>
  <head>
    <title>主頁</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body> 
    <%if(typeof(user) !== 'undefined' && user){%>
    <h1>Welcome <%= user.username %>, 歡迎登入!!</h1>  
    <a claa="btn" href="/logout">退出</a> 
    <%}else{%> 
        <h1>Welcome  , <a claa="btn" href="/login">請登入!!</a></h1>  
    <%}%> 
  </body>
</html>
當存在cookie的時候顯示使用者名稱,退出則銷燬cookie。 當不存在cookie的時候告訴使用者進行登入。

3.修改邏輯

修改index.js 我們添加了一個login頁面,那麼我們肯定需要相應的路由來渲染該頁面 新增login路由:
router.get('/login', function (req,res,next){   
  res.render('login')  
})
同理,新增index路由:
router.get('/index', function(req, res, next) {  
  res.render('index');
});
我們啟動服務訪問試試
$npm start

OK ,雖然醜陋了一點。 接下來我們處理一下邏輯 。 我們需要處理一個表單提交的邏輯,如果使用者名稱和密碼爭取則進入主頁,如果錯誤則提示錯誤資訊。 增加路由:
router.post('/login', function (req,res,next){   
  var username = req.body.username;
  var pwd = req.body.pwd;
  var user={  
    username:'admin',  
    pwd:123456  
  }  
  if(username==user.username && pwd==user.pwd){
    //設定cookie
    res.cookie("user", {username: username}, {maxAge: 600000 , httpOnly: false});
    res.redirect('index'); 
  }else{
    req.error = '使用者名稱密碼錯誤'
    res.render('login' , req) ;
  }  
  
})  
如果使用者名稱和密碼正確則設定一個cookie user   我們把使用者名稱存入cookie中  maxAge 為客戶端儲存cookie多長時間,單位是毫秒,如果省略這個選項,那麼瀏覽器關閉時 cookie就會被刪掉。 httpOnly 當這個選項為true時候,表明這個cookie只能有伺服器修改,也就是說不能使用js修改他,這個有助於防範xss攻擊。 我們設定了cookie當然需要使用它了 修改index路由
router.get('/index', function(req, res, next) {  
  if(req.cookies.user !== null){
    req.user=req.cookies.user;
  }
  res.render('index', req);
});
存在user這個cookie時候,把該cookie掛載在req.user中 ,這樣我們在前臺可以使用它。
我們還需要一個退出功能,增加路由
router.get('/logout', function (req,res,next){ 
  //刪除Cookie  
  res.clearCookie('user');
  res.redirect('index'); 
})
index.js完整程式碼
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/index', function(req, res, next) {  
  if(req.cookies.user !== null){
    req.user=req.cookies.user;
  }
  console.log(req.user)
  res.render('index', req);
});


router.get('/login', function (req,res,next){   
  res.render('login')  
})

router.post('/login', function (req,res,next){   
  var username = req.body.username;
  var pwd = req.body.pwd;
  var user={  
    username:'admin',  
    pwd:123456  
  }  
  if(username==user.username && pwd==user.pwd){

    res.cookie("user", {username: username}, {maxAge: 600000 , httpOnly: false});
    res.redirect('index'); 
  }else{
    req.error = '使用者名稱密碼錯誤'
    res.render('login' , req) ;
  }  
  
})  

router.get('/logout', function (req,res,next){ 
  //刪除Cookie  
  res.clearCookie('user');
  res.redirect('index'); 
})
module.exports = router;

這樣我們的專案就完成了,讓我們啟動試試看吧

4.專案預覽




5.httpOnly

當httpOnly為false 時候我們可以通過js修改它的cookie, 我們在控制檯輸入document.cookie="users="+123; 重新整理頁面,可以看到 多了一個users cookie, 同理我們也可以修改user的cookie,這是很不安全的。
當httpOnly為true的時候,我們發現不能這樣修改cookie,所以這個httpOnly有助於防範xxs攻擊

通常我們會設定一個包含唯一標識的cookie,然後伺服器通過這個標識來獲取相應的seesion。 seesion和cookie十分的相似,但是seesion是把資訊儲存在伺服器上,而cookie是把資訊儲存在客戶端,也就是本地。

5.session

使用session我們需要 express-session 中介軟體
$npm install express-session --save
注意:1.5.0版本之前該中介軟體需要依賴 cookie-parser,在這之後是不需要cookie-parser的,如果依賴了可能會報錯的 因為我們是1.5.0之後的版本,所以我們修改app.js
<pre name="code" class="javascript">
</pre><pre name="code" class="javascript">//第5行
var cookieParser = require('cookie-parser');
//修改為
var session = require('express-session');  
//第22行修改
app.use(cookieParser());
//修改為
app.use(session({secret:'test',name:"user" ,cookie:{maxAge: 6000 } })); 
其中

secret:用來對session資料進行加密的字串.這個屬性值為必須指定的屬性。name:表示cookie的name,預設cookie的name是:connect.sid。maxAge:cookie過期時間,毫秒。resave:是指每次請求都重新設定session cookie,假設你的cookie是6000毫秒過期,每次請求都會再設定6000毫秒。saveUninitialized: 是指無論有沒有session cookie,每次請求都設定個session cookie ,預設給個標示為 connect.sid。

修改index.js:
var express = require('express');
var router = express.Router();
 
router.get('/index', function(req, res, next) {  
  if(req.session.user!== null){
    req.user=req.session.user;
  }   
  console.log(req.user)
  res.render('index', req); 
});


router.get('/login', function (req,res,next){   
  res.render('login')  
})
 

router.post('/login', function (req,res,next){   
  var username = req.body.username;
  var pwd = req.body.pwd;
  var user={  
    username:'admin',  
    pwd:123456  
  }  
  if(username==user.username && pwd==user.pwd){
    req.session.user =  {username:username,pwd:123456};
    res.redirect('index'); 
  }else{
    req.error = '使用者名稱密碼錯誤'
    res.render('login' , req) ;
  }  
  
})  


router.get('/logout', function (req,res,next){ 
  //刪除Cookie   
  delete req.session.user;
  res.redirect('index'); 
})
module.exports = router;

OK,我們完成了使用session持久登入。

6.其他

上面的session使用是把資訊存在記憶體中,這樣有很多缺陷,比如說在我們重啟服務的時候,會發現session消失了。 有時候我們會想讓登入資訊保持很久,那麼我們存在記憶體中也是不太好的選擇。 我們可以把資訊儲存在資料庫中,mongodb和redis是很好的選擇。個人推薦redis。 具體的把資訊儲存在資料庫中本文不涉及暫時不涉及。