更新:
增加authentication
依赖库安装
1 2 3
| npm i passport npm i passport-local npm i passport-local-mongoose
|
UserSchema设计
1 2 3 4 5 6 7 8 9 10 11 12
| let mongoose = require("mongoose"); let passportLocalMongoose = require("passport-local-mongoose");
let UserSchema = new mongoose.Schema({ username: String, password: String });
//为User植入authentication各种方法 UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User",UserSchema);
|
值得注意的是, UserSchema中的属性名称必须为username和password
passport config
1 2 3 4 5 6 7 8 9 10
| app.use(require("express-session")({ secret: "My favorite gundam is exia!", resave: false, saveUninitialized: false, })); app.use(passport.initialize()); app.use(passport.session()); passport.use(new LocalStrategy(User.authenticate())); passport.serializeUser(User.serializeUser()); passport.deserializeUser(User.deserializeUser());
|
Routes设计
register设计:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| //=============== //AUTH ROUTES //=============== //show register form app.get("/register",function(req,res){ res.render("register"); }) //handle sign up request app.post("/register",function(req,res){ let newUser = new User({username: req.body.username}); //form与User中必须定义为username User.register(newUser, req.body.password, function(err, user){ if(err){ console.log(err); res.render("register"); } else { //验证登录 passport.authenticate("local", { successRedirect: '/wiki', failureRedirect: '/register', })(req, res, function(){ }) } }) })
|
在 register form中设计表项name 也必须为”username” “password”对应.
login设计:
1 2 3 4 5 6 7 8 9 10 11 12 13
| //show login form app.get("/login",function(req,res){ res.render("login"); })
//handle login request //app.post("login", middleware, callback) app.post("/login",passport.authenticate("local", { successRedirect: '/wiki', failureRedirect: '/login', }), function(req,res){ })
|
处于middleware的函数会被立即执行. passport.authenticate直接根据login form中的username 和 password 判断能否登录.
加密页面设置
设计函数isLoggedIn()如下:
1 2 3 4 5 6
| function isLoggedIn(req,res,next){ if(req.isAuthenticated()){ return next();//继续执行后续代码(下一个函数) } res.redirect("/login"); }
|
将该函数当做middleware function传入需要登录的页面对应的routes, 即可实现进入该页面前验证登录状态功能. 如: 需要用户登录之后才可以使用评论功能:
1
| app.get("/wiki/:id/comment/new",isLoggedIn ,function(req,res){
|
页面元素响应用户状态
为了实现页面根据用户状态不同而现实不同内容, 则需要将user信息传入对应route, 在express route中天然req.user即是用户信息结构体, 包含username, _id信息. 可以以参数形式传入:
1
| res.render("index",{User: req.user});
|
对于实现navbar随着用户状态而选择显示”Login”或”Logout”的功能, 需要在每个页面中都传入req.user数据. 为了简便, 可以使用app.use()功能, 该功能将参数函数当做middleware, 在每个route执行前运行, res.locals.currentUser设置res本地变量供ejs直接使用.
1 2 3 4
| app.use(function(req,res,next){ res.locals.currentUser = req.user; next(); });
|
易错点
- 定义UserSchema时属性必须为username, password.
- ejs的form中, 对应input的name也必须为username, password.
- bootstrap 4 的navbar需要靠右排列时, 使用
.ml-auto
类.
- navbar toggle dont work -> include JQuery!!!