[Day-10]延續Day9內容
四、將user存入session中
session是什麼,一種在client和server之間互相辨識的方法,套過server配發特定的session內容給client,
當下次client再次向server發出request時,使用這組session就可以認出是以登入過的使用者
因此在server和client端都需要保存此session資料。
一般來說,client端的session是存在cookie或是localstorage中,透過此sessionId到server的資料庫裡比對並拿到資料。
安裝express-session 以及 express-mysql-session套件
express-mysql-session可以將登入資訊存入mysql資料庫,這裡可以替換成其他資料庫選項(如mongoDb,redis等)
npm i express-session express-mysql-session --save
設定session資料庫連線
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);
var sessionStore = new MySQLStore(
connectionConfig
)
app.use(session({
secret: 'its a expressPassport auth' ,
resave: false,
saveUninitialized: true,
store: sessionStore,
}));
注意:session的中間件必須在passport前使用
app.use(passport.session())
將passport項開啟
passport.serializeUser(function (user, cb) {
cb(null, user.userId);
});
passport.deserializeUser(async function (id, cb) {
var user = await knex('user').select('*').where('user_id', id).limit(1)
cb(null, user[0])
});
改寫day9的兩個方法
其中序列化方法,表示在將session存入db時,user指存入userid
而反序列化方法,則根據傳入的id,到db查詢使用者資料,在存到req.user資料中
五、passport authenticate的自定義callback funtion
app.post('/login', function(req, res, next){
console.log(req.session)
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) { return res.json( { message: info.message }) }
req.logIn(user, function(err) {
if (err) return next(err);
return res.send('<div>登入成功 user information : ' + JSON.stringify(user) + '</div> <br> <a href="/"> return homepage</a>');
})
})(req, res, next);
});
在pass authenticate這裡因為是使用自定義的callback function
所以user資料並不會自動存入req中,需要手動呼叫login方法,後續才能在req中取得user
index
app.get('/', (req, res, next) => {
if(req.session.passport && req.session.passport.user){
res.send('hello ' + req.user.user_name + ',welcome to index');
}else{
res.send('<h1>Home</h1><p>未登入 <br>Please <a href="/login">login</a></p>');
}
});
登出
app.get('/logout', (re![https://ithelp.ithome.com.tw/upload/images/20200923/20110911HPSrrjnrN8.png](https://ithelp.ithome.com.tw/upload/images/20200923/20110911HPSrrjnrN8.png)q, res, next) => {
req.logout()
req.session.destroy()
res.redirect('/')
})
六、示範頁面
送出登入資訊
此時存在db中的session資料
T8hnMLemCYIliUApObiwzeqyiFxYWYsL,1600844097,"{""cookie"":{""originalMaxAge"":null,""expires"":null,""httpOnly"":true,""path"":""/""},""passport"":{""user"":18}}"
以userId存在裡面
返回homepage
使用deserializeUser方法到db中取得user資料,
並且req.user可以取得
按下登出後,清除session和req中的user,再次回到未登入狀態。
參考資料:https://andyyou.github.io/2017/04/11/express-passport/
http://www.passportjs.org/docs/authenticate/
[Day10結束]