Express结合Passport实现登陆认证
从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!
关于作者
- 张丹(Conan), 程序员Java,R,PHP,Javascript
- weibo:@Conan_Z
- blog: http://blog.fens.me
- email: [email protected]
转载请注明出处:
http://blog.fens.me/nodejs-express-passport/
前言
登陆认证,是每个应用都需要的基础功能。但很多的时候,却都被大家所忽略,不仅安全漏洞严重,而且代码紧耦合,混乱不堪。
Passport项目,正是为了解决登陆认证的事情,让认证模块更透明,减少耦合!
目录
- 什么是认证(Authentication)?
- Passport项目介绍
- Express结合Passport实现登陆认证
1. 什么是登陆认证(Authentication)?
认证又称“验证”、“鉴权”,是指通过一定的手段,完成对用户身份的确认。身份验证的方法有很多,基本上可分为:基于共享密钥的身份验证、基于生物学特征的身份验证和基于公开密钥加密算法的身份验证。
登陆认证,是用户在访问应用或者网站时,通过是先注册的用户名和密码,告诉应用使用者的身份,从而获得访问权限的一种操作。
几乎所有的应用都需要登陆认证!
2. Passport项目介绍
Passport项目是一个基于Nodejs的认证中间件。Passport目的只是为了“登陆认证”,因此,代码干净,易维护,可以方便地集成到其他的应用中。
Web应用一般有2种登陆认证的形式:
- 用户名和密码认证登陆
- OAuth认证登陆
Passport可以根据应用程序的特点,配置不同的认证机制。本文将介绍,用户名和密码的认证登陆。
3. Express结合Passport实现登陆认证
系统环境:
- Win7 64bit 旗舰版
- node v0.10.5
- npm 1.2.19
1). 新建项目
D:\workspace\javascript>express -e
nodejs-passport
D:\workspace\javascript>cd nodejs-passport
&& npm install
D:\workspace\javascript\nodejs-passport>npm
install passport
D:\workspace\javascript\nodejs-passport>npm
install passport-local
2). 实现Session的认证:
- 启用connet的session中间件
- connet的session中间件,同时依赖于connect的cookieParser中间件
- 配置passport中间件
关于connect框架的详细说明,请参考文章:Nodejs基础中间件Connect
修改app.js
app.use(express.cookieParser())
app.use(express.session({secret: ‘blog.fens.me‘,
cookie: { maxAge: 60000 }}));
app.use(passport.initialize());
app.use(passport.session());
3). 定义认证策略:
LocalStrategy策略,用于匹配本地环境的用户名和密码,可以扩展这个策略,通过数据库的方式进行匹配。
修改app.js
var passport = require(‘passport‘)
,
LocalStrategy = require(‘passport-local‘).Strategy;
passport.use(‘local‘, new LocalStrategy(
function (username, password, done) {
var
user = {
id: ‘1‘,
username: ‘admin‘,
password: ‘pass‘
};
// 可以配置通过数据库方式读取登陆账号
if
(username !== user.username) {
return done(null, false, { message: ‘Incorrect username.‘ });
}
if
(password !== user.password) {
return done(null, false, { message: ‘Incorrect password.‘ });
}
return done(null, user);
}
));
passport.serializeUser(function (user, done) {//保存user对象
done(null, user);//可以通过数据库方式操作
});
passport.deserializeUser(function (user, done)
{//删除user对象
done(null, user);//可以通过数据库方式操作
});
4). 路由控制和登陆认证
路由页面
- /: 首页,用于登陆,未登陆用户只能访问首页
- /login: 登陆请求,用户登陆时,POST到登陆请求,认证成功跳到用户页,认证失败回到首页
- /users: 用户页,用户通过登陆认证后,可以访问用户页
- /logout: 登出请求,用户退出系统,GET到登出请求,页面自动跳回首页
修改app.js
app.get(‘/‘, routes.index);
app.post(‘/login‘,
passport.authenticate(‘local‘, {
successRedirect: ‘/users‘,
failureRedirect: ‘/‘
}));
app.all(‘/users‘, isLoggedIn);
app.get(‘/users‘, user.list);
app.get(‘/logout‘, function (req, res) {
req.logout();
res.redirect(‘/‘);
});
function isLoggedIn(req, res, next) {
if
(req.isAuthenticated())
return next();
res.redirect(‘/‘);
}
5). 运行程序
运行日志
D:\workspace\javascript\nodejs-passport>node
app.js
Express server listening on port 3000
POST /login 302 389ms - 68b
GET /users 200 2ms - 50b
GET /logout 302 2ms - 58b
GET / 200 7ms - 540b
GET /stylesheets/style.css 304 6ms
POST /login 302 2ms - 58b
GET / 200 2ms - 540b
GET /stylesheets/style.css 304 2ms
6). 完整的代码
- app.js代码
- index.ejs代码
- user.js代码
app.js代码
var express = require(‘express‘)
,
routes = require(‘./routes‘)
, user
= require(‘./routes/user‘)
, http
= require(‘http‘)
, path
= require(‘path‘)
, app =
express();
var passport = require(‘passport‘)
,
LocalStrategy = require(‘passport-local‘).Strategy;
app.set(‘port‘, process.env.PORT || 3000);
app.set(‘views‘, __dirname + ‘/views‘);
app.set(‘view engine‘, ‘ejs‘);
app.use(express.favicon());
app.use(express.logger(‘dev‘));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser())
app.use(express.session({secret: ‘blog.fens.me‘,
cookie: { maxAge: 60000 }}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname,
‘public‘)));
if (‘development‘ == app.get(‘env‘)) {
app.use(express.errorHandler());
}
passport.use(‘local‘, new LocalStrategy(
function (username, password, done) {
var
user = {
id: ‘1‘,
username: ‘admin‘,
password: ‘pass‘
};
// 可以配置通过数据库方式读取登陆账号
if
(username !== user.username) {
return done(null, false, { message: ‘Incorrect username.‘ });
}
if
(password !== user.password) {
return done(null, false, { message: ‘Incorrect password.‘ });
}
return done(null, user);
}
));
passport.serializeUser(function (user, done) {//保存user对象
done(null, user);//可以通过数据库方式操作
});
passport.deserializeUser(function (user, done)
{//删除user对象
done(null, user);//可以通过数据库方式操作
});
app.get(‘/‘, routes.index);
app.post(‘/login‘,
passport.authenticate(‘local‘, {
successRedirect: ‘/users‘,
failureRedirect: ‘/‘
}));
app.all(‘/users‘, isLoggedIn);
app.get(‘/users‘, user.list);
app.get(‘/logout‘, function (req, res) {
req.logout();
res.redirect(‘/‘);
});
http.createServer(app).listen(app.get(‘port‘),
function () {
console.log(‘Express server listening on port ‘ + app.get(‘port‘));
});
function isLoggedIn(req, res, next) {
if
(req.isAuthenticated())
return next();
res.redirect(‘/‘);
}
index.ejs代码
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel=‘stylesheet‘
href=‘/stylesheets/style.css‘ />
</head>
<body>
<h1>Login</h1>
<form action="/login"
method="post">
<div>
<label>Username:</label>
<input type="text"
name="username"/>
</div>
<div>
<label>Password:</label>
<input type="password" name="password"/>
</div>
<div>
<input type="submit" value="Log
In"/>
</div>
</form>
</body>
</html>
user.js代码
exports.list = function (req, res) {
var html = "<h2>你好,
" + req.user.username + "</h2><a href=‘/logout‘>退出</a>";
res.send(html);
};
通过Passport中间件,我们就把登陆认证和应用程序分离了出来,从而保证了更清晰代码结构。当然,我们也可不用Passport,在Express中直接实现登陆认证,可以参考文章:Nodejs开发框架Express3.0开发手记–从零开始
Passport现实社交网络OAuth登陆
从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!
关于作者
- 张丹(Conan), 程序员Java,R,PHP,Javascript
- weibo:@Conan_Z
- blog: http://blog.fens.me
- email: [email protected]
转载请注明出处:
http://blog.fens.me/nodejs-oauth-passport/
前言
随着社交网络的发展,开发一个应用门槛越来越低。从一个完整的应用系统,到一个部署在社交网络平台的APP;从数据库–》应用层–》展示层,变成只需要开发展示层。
很多的社交应用,甚至都放弃了用户注册!仅靠大型社交网站的登陆授权,就可以赚到100W以上的用户量。。。
减少用户管理代码开发及维护,更专注于应用本身,个人开发者已经崛起!!
目录
- Passport介绍
- OAuth介绍
- 登陆Github
- 登陆LinkedIn
1. Passport介绍
Passport项目,主要是为了解决登陆认证的问题。
Web应用一般有2种登陆认证的形式:
- 用户名和密码认证登陆
- OAuth认证登陆
在上一篇文章中,我们介绍了Passport的项目,通过用户名和密码认证登陆。Express结合Passport实现登陆认证
本文将介绍,通过Passport实现OAuth登陆认证。
2. OAuth介绍
OAuth协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAuth的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAuth是安全的。
- 简单:不管是OAUTH服务提供者还是应用开发者,都很易于理解与使用
- 安全:没有涉及到用户密钥等信息,更安全更灵活
- 开放:任何服务提供商都可以实现OAUTH,任何软件开发商都可以使用OAUTH
OAuth认证授权就三个步骤,三句话可以概括:
- 获取未授权的Request Token
- 获取用户授权的Request Token
- 用授权的Request Token换取Access Token
OAuth的介绍,摘自:http://baike.baidu.com/view/3948029.htm
3. Github登陆
通过Passport实现Github登陆。我们还使用上一篇文章中的环境:Express结合Passport实现登陆认证
- 申请开发github应用
- Passport程序实现
- 运行Github登陆认证
1). 申请开发github应用
2). Passport程序实现
- 安装Passport的github扩展
- 增加Github认证策略
- 定义Github认证的路由配置: 登陆,回调,展示
a. 安装Passport的github扩展
D:\workspace\javascript\nodejs-passport>npm install passport-github
b. 增加Github认证策略
修改app.js
passport.use(new GithubStrategy({//对应从Github申请KEY
clientID: "XXXX",
clientSecret: "XXXX",
callbackURL:
"http://localhost:3000/auth/github/callback"
},function(accessToken, refreshToken, profile, done) {
done(null, profile);
}));
c. 定义Github认证的路由配置: 登陆,回调,展示
- /auth/github: 通过github,登陆
- /auth/github/callback: github认证成功后,回调
- /github: 回调验证后,转向展示示
修改app.js
app.all(‘/github‘, isLoggedIn);
app.get("/github",user.github);
app.get("/auth/github",
passport.authenticate("github",{ scope : "email"}));
app.get("/auth/github/callback",
passport.authenticate("github",{
successRedirect: ‘/github‘,
failureRedirect: ‘/‘
}));
3).运行Github登陆认证
程序日志
D:\workspace\javascript\nodejs-passport>node app.js
Express server listening on port 3000
GET / 200 401ms - 594b
GET /stylesheets/style.css 304 9ms
GET /auth/github 302 8ms - 424b
GET /auth/github/callback?code=7cf818c4590e2aacfe90 302 4052ms - 70b
GET /github 200 4ms - 139b
GET /logout 302 2ms - 58b
GET / 200 3ms - 594b
GET /stylesheets/style.css 304 2ms
4. LinkedIn登陆
- 申请开发LinkedIn应用
- Passport程序实现
- 运行LinkedIn登陆认证
1). 申请开发LinkedIn应用
2). Passport程序实现
- 安装Passport的LinkedIn扩展
- 增加LinkedIn认证策略
- 定义LinkedIn认证的路由配置: 登陆,回调,展示
a. 安装Passport的LinkedIn扩展
D:\workspace\javascript\nodejs-passport>npm install passport-linkedin
b. 增加LinkedIn认证策略
修改app.js
passport.use(new LinkedinStrategy({
consumerKey: "XXXX",
consumerSecret:
"XXXX",
callbackURL:
"http://localhost:3000/auth/linkedin/callback",
userAgent: ‘localhost‘
},function(accessToken, refreshToken, profile, done) {
done(null, profile);
}));
c. 定义LinkedIn认证的路由配置: 登陆,回调,展示
- /auth/linkedin: 通过LinkedIn,登陆
- /auth/linkedin/callback: github认证成功后,回调
- /linkedin: 回调验证后,转向展示示
修改app.js
app.all(‘/github‘, isLoggedIn);
app.get("/github",user.github);
app.all(‘/linkedin‘, isLoggedIn);
app.get("/linkedin",user.linkedin);
app.get("/auth/linkedin",
passport.authenticate("linkedin",{}));
app.get("/auth/linkedin/callback",
passport.authenticate("linkedin",{
successRedirect:
‘/linkedin‘,
failureRedirect: ‘/‘
}));
3).运行LinkedIn登陆认证
程序日志
D:\workspace\javascript\nodejs-passport>node app.js
Express server listening on port 3000
GET / 200 399ms - 638b
GET /stylesheets/style.css 304 4ms
GET /auth/Linkedin 302 3092ms - 256b
GET
/auth/linkedin/callback?oauth_token=75--8f032180-afae-489b-bc3c-3326d80bea6f&oauth_verifier=36091
302 3049ms - 74b
GET /linkedin 200 5ms - 76b
GET /logout 302 1ms - 58b
GET / 200 19ms - 638b
GET /stylesheets/style.css 304 2ms
5. 完整的应用
项目代码我已上传到了github, 项目地址:https://github.com/bsspirit/nodejs-passport
下载及安装
git clone https://github.com/bsspirit/nodejs-passport
npm install
我们非常方便地,实现了Github和LinkedIn登陆认证,是否已经体会到Passport的强大了!把权限这种基础功能,进行合理的封装,是会帮我们节省大量的工作量的