您的位置:首页 > Web前端 > Node.js

Node.js项目实战-构建可扩展的Web应用(第一版): 6 在Node.js应用中使用session和OAuth进行用户认证和授权

2018-01-11 20:11 1041 查看

6.1  使用Express.js中间件实现权限管理

“权限管理”指面向不同的用户开放不同的页面(或接口)权限

URL的权限:app.get('/api/*', auth)

6.2 基于token的用户认证

   为不同用户赋予不同的权限,所以需要在auto()函数中添加用户认证的流程。

   最常见的方案是基于cookie或session授权管理。但有些不适用,比如使用REST架构的应用,更有效的方案是在每次请求中都携带token(比较常见的OAuth2.0协议),也可以是E-mail和密码、API密钥、API密码等。

6.3 基于session的用户认证

    $ npm install cookie-parser       //解析发送的和接收的cookie

    $ npm install express-session   //在每个请求体中暴露res.session对象,并且在内存或持久化存储中session数据

    警告:cookie十分不安全,而且存储长度小,推荐的方法是:不去手动操作cookie,只保留session ID字段,由Express.js中间件自动控制

   使用Redis或者MongoDB存储session数据,这样既可以保证session数据能够持久化存储也可以实现session数据可跨服务器读取。

6.4 项目实践:为博客增加邮箱和密码登录功能用户认证

    为了在博客中实现基于session的用户认证,需要以下步骤:

在app.js的配置部分中增加引入和使用session中间件的代码。
实现一个基于session的用户认证中间件,以便我们在多个路由规则之间复用这些代码。
在app.js文件中添加上一步骤中的中间件,以控制非公开页面的访问。
在user.js中实现包含认证过程的登录路由POST /login和登出路由GET  /logout

session中间件:在app.js中加入

//定义中间件
app.use(cookieParser('3CCC4ACD-6ED1-4844-9217-82131BDCB239'));
//session需要依赖cookie才能正常工作
app.use(session({secret: '2C44774A-D649-4D44-9535-46E296EF984F'})); 博客中的权限管理:通过检查req.session.admin标记的是否为真。
// 引入依赖
var express = require('express');
var http = require('http');
var path = require('path');
var mongoskin = require('mongoskin');
var dbUrl = process.env.MONGOHQ_URL || 'mongodb://@localhost:27017/blog';
var db = mongoskin.db(dbUrl, {saft: true});
var collections = { articles: db.collection('articles'),
users: db.collection('users')};
// 引入Express.js中间件
var cookieParser = require('cookie-parser');
var session = require('express-session');
var logger = require('morgan');
var errorHandler = require('errorhandler');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//设置相关配置
var app = express();
app.locals.appTitle = 'blog-express';
//处理请求中的查询
app.use( function(req, res, next) {
if (!collections.articles || !collections.users)
return next(new Error('No collections.'));
req.collections = collections;
return next();
});
// Express.js 配置
//app.set('appName', 'hello-world');
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// Express.js 中间件配置
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser('3CCC4ACD-6ED1-4844-9217-82131BDCB239'));
//session需要依赖cookie才能正常工作
app.use(session({secret: '2C44774A-D649-4D44-9535-46E296EF984F'}));
app.use(methodOverride());
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
//用户认证中间件
app.use(function(req, res, next) {
if (req.session && req.session.admin)
res.locals.admin = true;
next();
});
//权限管理
var authorize = function(req, res, next) {
if (req.session && req.session.admin)
return next();
else
return res.send(401);
};
if ('development' == app.get('env')) {
app.use(errorHandler());
}
//页面路由
app.get('/', routes.index);
app.get('/login', routes.user.login);
app.post('/login', routes.user.authenticate);
app.get('/logout', routes.use.logout);
app.get('/admin', authorize, routes.article.admin);
app.get('/post', authorize, routes.article.post);
app.post('/post', authorize, routes.article.postArticle);
app.get('/articles/:slug', routes.article.show);
// REST API路由
app.all('/api', authorize);
app.get('/api/article', routes.article.list);
app.port('/api/article', routes.article.add);
app.put('/api/article/:id', routes.article.edit);
app.del('/api/article/:id', routes.article.del);

app.all('*', function(req, res) {
res.send(404);
})
//启动服务
var server = http.createServer(app);
var boot = function() {
server.listen(app.get('port'), function() {
console.log('Express server listening on port' + app.get('port'));
});
}
var shutdown = function() {
server.close();
}
if (require.main === module) {
boot();
} else {
console.info('Running app as a module');
exports.boot = boot;
exports.shutdown = shutdown;
exports.port = app.get('port');
}
//在多核系统上启动cluster多核处理模块(可选)博客中的用户授权:用户的身份是管理员,则设置admin=true。在user.js中的toutes.user.authenticate。
//
exports.list = function(req, res) {
res.send('respond with a resource');
};

exports.login = function(req, res, next) {
res.render('login');
};

exports.logout = function(req, res, next) {
req.session.destroy();
res.redirect('/');
};
//用户授权
exports.authenticate = function(req, res, next) {
if (!req.body.email || !req.body.password)
return res.render('login', {error: 'Please enter your email and password.'});
req.collections.users.findOne({
email: req.body.email,
password: req.body.password
}, fucntion(error, user) {
if (error) return next(error);
if (!user) return res.render('login', {error: 'Incorrect email&password combination.'});
req.session.user = user;
req.session.admin = user.admin;
redds.redirect('/admin');
})
};

6.5 Node.js OAuth组件

    OAuth模块可以帮我们计算签名、编码信息、生成HTTP头,最后发送模块。需要完成:发起OAuth握手(即在服务商、用户以及我们的应用之间的一系列请求)、添加回调路由、在session或数据库中存储信息等。可以参考服务商提供的文档,来获取关于接口、方法、参数等内容更详细的说明。

    $ npm install oauth

6.6 项目实践:为博客增加Twitter OAuth 1.0第三方登录

  使用Everyauth实现:自带市面上大部分第三方服务商的OAuth配置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐