细谈Node.js项目实战

     使用node.js开发的token用户验证的网站很多,典型的网站,如猪八戒威客网站,使用了node.js技术。

在网站应用中,会为不同的用户赋予不同的权限(比如为管理员账户赋予较高的权限),所以我们需要在auto()函数中添加用户认证的流程。

一般来讲,最常见的方案是基于cookie 或session 授权管理,但某些场景下这种方案并不适用,比如对要求使用REST 架构的应用,或客户端对cookie\session 支持不佳(如移动端)等。更有效的方案是在每次请求中都携带token(比较常见的OAuth2.0 协议3),并在服务端通过token 进行独立的认证。这里既可以把token 字段加载到请求参数中,也可以添加到HTTP 请求头中。当然这里也可以是其他认证信息,比如E-mail 和密码、API 密钥、API 密码等。

在我们的示例中,每个请求都会提交token 字段,并在接收时把token(通过req.query.token 获取)和应用中储存的token(通常使用数据库储存,或如本例中简单地保存在SECRET_TOKEN 常量中)进行比对。如果比对通过则调用next()方法继续后续处理,如果不通过则调用next(error)触发Express.js 的错误响应:
 

 
 
  
  
  
  
  1. var auth = function(req, res, next) {  
  2. if (req.query.token && token === SECRET_TOKEN) {  
  3. // 校验通过,进行下一阶段处理  
  4. return next();  
  5. } else {  
  6. return next(new Error('Not authorized'));  
  7. // 也可以 res.send(401);  
  8. }  
  9. }; 

在实践中,一般使用API 的key 和secret 生成HMAC-SHA1(一种基于散列的信息加密算法)字符串,并把它和接收到的token(req.query.token)进行比对。

注意 在调用next()方法时传入一个error 对象作为参数,表示放弃请求处理,这时会触发Express.js 的错误模式,并进入错误处理流程。

我们刚才介绍了REST API 中常用的基于token 的认证模式。另外一种常见模式是使用cookie 进行用户认证,这种模式在含有用户界面的应用中经常使用。我们使用cookie 储存session ID,并在请求时自动提交。从某种意义上讲,cookie 有些类似于token,但是cookie使用较为方便,并不需要开发者做太多的工作。基于session 的认证就是使用这种模式。基于session 的认证在Web 应用中十分常见,也更受推崇,因为浏览器可以自动处理带有session 的请求头,而且大多数的后端平台或框架也能原生支持session。接下来,就让我们一起进入在Node.js 中实现基于session 的用户认证这一小节吧。

   

基于session 的用户认证

基于session 的用户认证借助于请求体对象req 中的session 对象完成。简单地说,session 可以鉴别客户端,并对应地储存信息,供同一客户端所有的后续请求读取。

在Express.js 4.x 版(4.1.2 版以及写本书时使用的4.2.0 版)中,我们需要手动引入(require())操作session 所依赖的模块,因为Express.js 4.x 把它们从核心包中剔除了。例如,引入并使用cookie-parser 和express-session 模块:
 

 
 
  
  
  
  
  1. var session = require('express-session');  
  2. ...  
  3. app.use(cookieParser());  
  4. app.use(session()); 

当然,在进行这些操作之前,cookie-parser 模块和express-session 模块需要通过NPM 安装到项目的node_modules 文件夹中。

如果是在经典的Express.js 3.x 版本中,则需要在配置文件中加入下面两个中间件。

1. express.cookieParser():解析发送的和接收的cookie。

2. express.session():在每个请求体中暴露res.session 对象,并且在内存或持久化存储中(如MongoDB、Redis 等)储存session 数据。

在后文的例子中,如果没有特别提及Express.js 的版本,就表示代码能兼容3.x 和4.x
版本。

啰唆一句,我们可以在req.session 中储存任何数据,它们会自动出现在来自同一个客户端的所有后续请求中(在客户端支持cookie 的前提下)。在这个例子中,认证信息用session 储存的一个标记(布尔值),我们在授权函数中去检查这个标记,为真放行,为假则退出。像这样敲击代码:

 
 
  
  
  
  
  1. app.post('/login', function(req, res, next) {  
  2. // 检查凭证  
  3. // 在请求的有效负载中进行传递  
  4. if (checkForCredentials(req)) {  
  5. req.session.auth = true;  
  6. res.redirect('/dashboard'); // 非公开内容  
  7. } else {  
  8. res.send(401); // 认证不通过  
  9. }  
  10. }); 

警告 避免在cookie 中储存任何敏感信息。因为cookie 十分不安全,而且储存长度存在限制(不同的浏览器限制不同,IE 最小)。所以推荐的方法是:不去手动操作cookie,cookie 中只保留session ID 字段,这个字段由Express.js 中间件自动控制。

Express.js 默认使用内存来储存session 数据,这就表示每次应用崩溃或手动重启时session 数据都会丢失。我们可以使用Redis 或者MongoDB 储存session 数据,这样既可以保证session 数据能够持久化存储也可以实现session 数据可跨服务器读取

为你的博客增加邮箱和密码登录功能

你的博客中实现基于session 的用户认证,我们需要完成以下步骤:

1. 在app.js 的配置部分中增加引入和使用session 中间件的代码。

2. 实现一个基于session 的用户认证中间件,以便我们在多个路由规则之间复用这些代码。

3. 在app.js 文件中添加上一步骤中的中间件,以控制非公开页面的访问。像这样:

app.get('/api/', authorize, api.index)

4. 在user.js 中实现包含认证过程的登录路由POST /login 和登出路由GET/logout。
 


 


你可能感兴趣的:(细谈Node.js项目实战)