我刚刚开始passport.js。从this article开始,我得到了所有护照方法的流程,并在我的应用程序中实现了相同的工作方式。这是我的server.js,我正在使用passport-local
策略。同一服务器上的Angular app和rest API
import { registerControllersFromFolder } from 'giuseppe';
import { MessageManager } from './messaging/MessageManager';
import express = require('express');
import bodyParser = require('body-parser');
import session = require("express-session");
import http = require('http');
// class to hold user info
class User {
userId: number;
userName: string;
constructor(userId: number, userName: string) {
this.userId = userId;
this.userName = userName;
}
}
// server class to create http server
export class Server {
// list of apis for which authentication is not required
private static publicApiList: string[] = ["/services/login", "/login", "/favicon.ico"];
// request interceptor that will check user authentication
private static isAuthenticated = (req, res, next) => {
console.log("Authenticating :", req.originalUrl);
if (req.isAuthenticated() || Server.publicApiList.indexOf(req.originalUrl) > -1) {
// express routing
if (req.originalUrl.startsWith("/services")) {
console.log("Express Routing");
return next();
} else { // angular routing -> return index.html
console.log("Angular Routing");
return res.sendFile(__dirname + "/public/index.html");
}
} else {
console.log("User not authenticated.")
res.redirect('/');
}
};
static startServer() {
let userList: User[] = [new User(1, "Sunil"), new User(2, "Sukhi")];
let app = express();
// passport library
let passport = require('passport');
let LocalStrategy = require('passport-local').Strategy;
// middlewares
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ resave: false, saveUninitialized: true, secret: "secretKey123!!" }));
// passport middleware invoked on every request to ensure session contains passport.user object
app.use(passport.initialize());
// load seriliazed session user object to req.user
app.use(passport.session());
// Only during the authentication to specify what user information should be stored in the session.
passport.serializeUser(function (user, done) {
console.log("Serializer : ", user);
done(null, user);
});
// Invoked on every request by passport.session
passport.deserializeUser(function (user, done) {
let validUser = userList.filter(user => user.userId === user.userId)[0];
console.log("D-serializer : ", validUser);
done(null,validUser);
});
// passport strategy : Only invoked on the route which uses the passport.authenticate middleware.
passport.use(new LocalStrategy({
usernameField: 'name',
passwordField: 'password'
},
function (username, password, done) {
console.log("Strategy : Authenticating if user is valid :", username)
let user = userList.filter(user => username === user.userName);
console.log("Valid user : ", user)
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
return done(null, user[0]);
}
));
// intercept request for authentication
app.use(Server.isAuthenticated);
app.post('/services/login', passport.authenticate('local', {
successRedirect: '/profile',
failureRedirect: '/login'
}));
app.get('/services/logout', (req: any, res: any) => {
req.logout();
console.log("User Logout");
res.send("{status:'logout'}")
});
// http server creation
let server = http.createServer(app);
registerControllersFromFolder({ folderPath: './api' })
.then(router => {
app.use(router);
/* start express server */
})
.catch(err => {
/* error happened during loading and registering */
});
server.listen(7000, () => {
console.log('Up and running on port 7000');
});
}
}
exports.startServer = Server.startServer;
// Call a module's exported functions directly from the command line.
require('make-runnable');
当我点击localhost:7000
时,它会按照我使用的 index.html 页面提供
app.use(express.static(__dirname + "/public"));
这是一个角度应用程序,因为角度路由login
模块将默认加载。我使用了一个检查请求身份验证的中间件,如果是,则基于请求前缀(有角度或快速)路由完成。
对于定义的登录请求,调用本地策略方法,如果这是真的,则调用serializer
方法,该方法负责将数据存储在请求会话中。然后调用sucessRedirect
或failureRedirect
。
对于后续请求,因为我使用了检查req.isAuthenticated
是否为真的中间件,如果是,则提供请求,否则将用户重定向到登录页面。我知道在每个后续请求deserializeUser
方法中都会调用包含serializeUser
方法在登录请求中存储的对象的方法。根据文档,这会调用数据库来检查有效用户。
但我很困惑,但是deserializeUser
方法的实际用例?我在哪里可以利用这种方法,如果我拦截ecah请求并检查req.isAuthenticted(),那么为什么要用deserializeUser
方法调用数据库?>
答案 0 :(得分:0)
deserializeUser
的第一个参数对应于的关键字 提供给done函数的用户对象(参见1.)。所以你的 借助该键检索整个对象。这里的关键是 用户ID(密钥可以是用户对象的任何密钥,即名称,电子邮件等)。 在deserializeUser
中,该键与内存数组匹配/ 数据库或任何数据资源。获取的对象作为
附加到请求对象req.user
因此,deserializeUser
的好处是您之后的每个请求都有可用的用户对象。
如果您致电deserializeUser
,请问为什么需要使用req.isAuthenticated
,答案在于req.isAuthenticated
的实施:
req.isAuthenticated = function() {
var property = 'user';
if (this._passport && this._passport.instance) {
property = this._passport.instance._userProperty || 'user';
}
return (this[property]) ? true : false;
};
对我而言,req.isAuthenticated
似乎正在寻找req[user]
,因此,deserializeUser
必须先调用才能正常工作。