认证

npm version Changelog

$ npm install @feathersjs/authentication --save

@feathersjs/authentication 模块帮助使用JWT进行身份验证. 它有三个主要目的:

  1. 设置 /authentication 端点以创建JSON Web令牌(JWT). JWT用作访问令牌. 您可以在 jwt.io 了解更多关于JWT的信息.

  2. 为所有Feathers传输提供一致的身份验证API

  3. 为使用 Passport 策略保护端点的身份验证插件提供框架.

注解

If you are using a 0.x version of migration guide. The hooks that were once bundled with this module are now located at feathers-authentication-hooks.

互补插件

以下插件是互补的, 但完全是可选的:

app.configure(auth(options))

使用给定选项配置身份验证插件. 对于未提供的选项, 将使用 default options.

const auth = require('@feathersjs/authentication');

// Available options are listed in the "Default Options" section
app.configure(auth(options))

重要

在任何其他服务 之前, 必须配置插件.

选项

以下默认选项将与配置文件中的全局 auth 对象混合在一起.它会将混合选项设置回应用程序, 以便通过调用 app.get('authentication') 随时可用.它们都可以被覆盖, 并且是某些身份验证插件所必需的.

{
 path: '/authentication', // the authentication service path
 header: 'Authorization', // the header to use when using JWT auth
 entity: 'user', // the entity that will be added to the request, socket, and context.params. (ie. req.user, socket.user, context.params.user)
 secret: 'supersecret', // either the secret for HMAC algorithms or the PEM encoded private key for RSA and ECDSA.
 service: 'users', // the service to look up the entity
 passReqToCallback: true, // whether the request object should be passed to the strategies `verify` function
 session: false, // whether to use sessions
 cookie: {
  enabled: false, // whether cookie creation is enabled
  name: 'feathers-jwt', // the cookie name
  httpOnly: false, // when enabled, prevents the client from reading the cookie.
  secure: true // whether cookies should only be available over HTTPS
 },
 jwt: {
  header: { typ: 'access' }, // by default is an access token but can be any type. This is not a typo!
  audience: 'https://yourdomain.com', // The resource server where the token is processed
  subject: 'anonymous', // Typically the entity id associated with the JWT
  issuer: 'feathers', // The issuing server, application or resource
  algorithm: 'HS256', // the algorithm to use
  expiresIn: '1d' // the access token expiry
 }
}

注解

The typ in the JWT header options is not a typo. It is the typ parameter defined in the JWT specification.

app.service(‘authentication’)

这个插件的核心是一个创建JWT的服务. 这是一个普通的Feathers服务, 它只实现了 create` `和 ``remove 方法. /authentication 服务提供``/auth/local`` 和 /auth/token 端点所具有的所有功能. 要选择策略, 客户端必须在请求正文中传递 strategy 名称. 根据使用的插件, 这将有所不同. 有关详细信息, 请参阅本页顶部列出的插件的文档.

service.create(data)

几乎每个Feathers应用程序都会使用 create 方法. 它基于插件上配置的 jwt 选项创建了一个JWT. 此方法的API使用 context 对象.

如果您手动生成JWT, 例如, 想要使用 `payload <https://jwt.io>`_``{userId:“abc123 ”}``创建一个JWT. :

const data = {payload: {userId: "abc123"}};
service.create(data);

例如, 如果您手动生成JWT, 则需要使用`payload <https://jwt.io>`_`` {userId:“abc123 ”}``创建JWT.

service.remove(data)

较少使用 remove 方法.它的主要目的是为“注销”过程添加钩子.例如, 在需要高度安全控制的服务中, 开发人员可以在执行令牌黑名单的 remove 方法上注册挂钩.

service.hooks({ before })

可以修改这些属性以更改``/authentication``服务的行为:

  • context.data.payload {Object} - 确定JWT的有效载荷

  • context.params.payload {Object} - 还确定了JWT的有效载荷. “context.data.payload”中的任何匹配属性都将被这些覆盖. 坚持后钩.

  • context.params.authenticated {Boolean} - 成功验证后, 将被设置为``true``, 除非它在before hook中设置为``false``.如果在before hook中将其设置为“false”, 则会阻止websocket被标记为已验证.坚持后钩.

service.hooks({ after })

  • context.params[entity] {Object} - 成功验证后, 将在此处填充从数据库中查找的``entity``. (默认选项是``user``. )

app.passport

app.passport.createJWT(payload, options)

``app.passport.createJWT(payload, options) -> 承诺``由`authentication service <#appserviceauthentication>`_用于生成JSON Web令牌.

  • payload {Object} - 成为JWT有效载荷. 还将包含一个表示到期时间戳的``exp``属性.

  • options {Object} - the options passed to jsonwebtoken sign()

  • secret {String | Buffer} - 要么是HMAC算法的秘密, 要么是用于RSA和ECDSA的PEM编码私钥.

  • jwt - 有关其他可用选项, 请参阅 jsonwebtoken package docs. authenticate方法使用 default jwt ``选项<#default-options>`_.直接使用此包时, 必须手动传递它们.

返回的 promise 用JWT解析或失败并出错.

app.passport.verifyJWT(token, options)

使用``options``验证传入的JWT``token``的签名和有效负载.

返回的``promise``使用有效负载解析或失败并显示错误.

auth.hooks.authenticate(strategies)

``@feathersjs/authentication``只包含一个钩子. 这个捆绑的``authenticate``钩子用于在服务方法上注册一组认证策略.

注解

这应该通常用在你的``/authentication``服务上. 没有它, 您可以点击``authentication``服务并生成JWT``adminToken``而无需身份验证(即匿名身份验证).

app.service('authentication').hooks({
 before: {
  create: [
   // You can chain multiple strategies
   auth.hooks.authenticate(['jwt', 'local']),
  ],
  remove: [
   auth.hooks.authenticate('jwt')
  ]
 }
});

认证事件

只要客户端成功验证或“注销”, 就会在``app``对象上发出``login``和``logout``事件. (使用JWT时, 注销不会使JWT无效.(有关详细信息, 请阅读JWT部分.)这些事件仅在服务器上发出.

app.on(‘login’, callback))

app.on(‘logout’, callback))

这两个事件使用具有相同签名的``callback``函数.

  • result {Object} - 来自``authentication``服务的最终``context.result``.除非你在后钩子中自定义``context.response``, 否则它只包含``accessToken``, 它是JWT.

  • meta {Object} - information about the request. The ``meta`` data varies per transport / provider as follows.

    • Using @feathersjs/express/rest

      • provider {String} - 永远是``“rest ”``

      • req {Object} - Express请求对象.

      • res {Object} - Express响应对象.

    • 使用``feathers-socketio``和``feathers-primus``:

      • provider {String} - 传输名称:socketio``或``primus

      • connection {Object} - 与钩子上下文中的``params``相同

      • socket {SocketObject} - 当前用户的WebSocket对象. 它还包含``feathers``属性, 它与钩子上下文中的``params``相同.

快递中间件

有一个``authenticate``中间件. 它的使用方法与普通的Passport express中间件完全相同:

const cookieParser = require('cookie-parser');

app.post('/protected-route', cookieParser(), auth.express.authenticate('jwt'));
app.post('/protected-route-that-redirects', cookieParser(), auth.express.authenticate('jwt', {
  failureRedirect: '/login'
}));

有关详细信息, 请参阅:doc:../../guides/auth/recipe.express-middleware.

包含并公开了其他中间件, 但您通常不需要担心它们:

  • emitEvents - 发出``login``和``logout``事件

  • exposeCookies - 向Feathers公开cookie, 以便它们可用于钩子和服务. **默认情况下不使用它, 因为它的使用会将您的API暴露给CSRF漏洞.**只有在您真正知道自己在做什么的情况下才使用它.

  • exposeHeaders - 向Feathers公开标题, 以便它们可用于钩子和服务. **默认情况下不使用它, 因为它的使用会将您的API暴露给CSRF漏洞.**只有在您真正知道自己在做什么的情况下才使用它.

  • failureRedirect - 支持重定向auth失败. 仅在设置了``hook.redirect``时触发.

  • successRedirect - 支持重定向auth成功. 仅在设置了``hook.redirect``时触发.

  • setCookie - 支持在cookie中设置JWT访问令牌. 仅在启用cookie时启用.

注解

Feathers不会从cookie中读取访问令牌. 这会使API暴露于CSRF攻击. **这个 setCookie 功能主要用于帮助进行服务器端渲染.

完整的例子

这是一个使用 @feathersjs/authentication 进行本地身份验证的Feathers服务器的示例.

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');
const auth = require('@feathersjs/authentication');
const local = require('@feathersjs/authentication-local');
const jwt = require('@feathersjs/authentication-jwt');
const memory = require('feathers-memory');

const app = express(feathers());
app.configure(express.rest())
 .configure(socketio())
 .use(express.json())
 .use(express.urlencoded({ extended: true }))
 .configure(auth({ secret: 'supersecret' }))
 .configure(local())
 .configure(jwt())
 .use('/users', memory())
 .use('/', express.static(__dirname + '/public'))
 .use(express.errorHandler());

app.service('users').hooks({
  // Make sure `password` never gets sent to the client
  after: local.hooks.protect('password')
});

app.service('authentication').hooks({
 before: {
  create: [
   // You can chain multiple strategies
   auth.hooks.authenticate(['jwt', 'local'])
  ],
  remove: [
   auth.hooks.authenticate('jwt')
  ]
 }
});

// Add a hook to the user service that automatically replaces
// the password with a hash of the password, before saving it.
app.service('users').hooks({
 before: {
  find: [
   auth.hooks.authenticate('jwt')
  ],
  create: [
   local.hooks.hashPassword({ passwordField: 'password' })
  ]
 }
});

const port = 3030;
let server = app.listen(port);
server.on('listening', function() {
 console.log(`Feathers application started on localhost:${port}`);
});