跳到主要内容
版本号:Next

认证插件

什么是身份验证插件?

它是一种插件,允许管理谁可以访问或发布到特定的软件包。 默认情况下,内置了htpasswd,但可以轻松地被你自己替换。

开始

认证插件在 auth: 部分中定义,如下所示:

auth:
htpasswd:
file: ./htpasswd

还可以将多个插件串联起来:

auth:
htpasswd:
file: ./htpasswd
anotherAuth:
foo: bar
bar: foo
lastPlugin:
foo: bar
bar: foo

如果链中的一个插件能够处理请求,那么接下来的插件将被忽略。

认证插件是如何工作的?

基本上我们需要返回一个带有一个名为 authenticate 的方法的对象,该方法将接收3个参数(user, password, callback)。

在每次请求上,authenticate将被触发,插件应返回凭据,如果 authenticate 失败,它将默认回退到 $anonymous 角色。

API

interface IPluginAuth<T> extends IPlugin<T> {
authenticate(user: string, password: string, cb: AuthCallback): void;
adduser?(user: string, password: string, cb: AuthCallback): void;
changePassword?(user: string, password: string, newPassword: string, cb: AuthCallback): void;
allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
allow_unpublish?(
user: RemoteUser,
pkg: AllowAccess & PackageAccess,
cb: AuthAccessCallback
): void;
apiJWTmiddleware?(helpers: any): Function;
}

只有 adduser, allow_access, apiJWTmiddleware, allow_publishallow_unpublish 是可选的,verdaccio 在所有这些情况下提供了备用方案。

apiJWTmiddleware 方法

v4.0.0

apiJWTmiddleware 是在 PR#1227 上引入的,以便完全控制令牌处理程序,重写此方法将禁用 login/adduser 支持。 我们建议除非完全必要,否则不要实现此方法。 请参阅此处的完整示例。

我应该在每个方法中返回什么?

在撰写本文时,Verdaccio 依靠的是 callback 函数。 每个方法都应调用方法,返回的内容很重要,让我们回顾一下如何做到这一点。

authentication 回调

身份验证执行完毕后,有两个选项可以向 verdaccio 提供响应。

如果认证失败

如果验证不成功,则返回 false 作为第二个参数。

callback(null, false);
如果认证成功

授权成功。

groups 是用户所属组的字符串数组。

 callback(null, groups);
如果身份验证产生错误

身份验证服务可能会失败,您可能希望在用户响应中反映这一点,例如:服务不可用。

 import { getInternalError } from '@verdaccio/commons-api';

callback(getInternalError('something bad message), null);

登录失败与服务错误不同,如果要通知用户凭据有误,只需返回 false 而不是 groups 列表。 该行为主要取决于您。

adduser 回调

如果添加用户成功

如果服务能够创建用户,则返回 true 作为第二个参数。

callback(null, true);
如果添加用户失败

除成功之外的任何其他操作都必须返回错误。

import { getConflict } from '@verdaccio/commons-api';

const err = getConflict('maximum amount of users reached');

callback(err);

changePassword 回调

如果请求成功

如果服务能够创建用户,则返回 true 作为第二个参数。

const user = serviceUpdatePassword(user, password, newPassword);

callback(null, user);
如果请求失败

除成功之外的任何其他操作都必须返回错误。

import { getNotFound } from '@verdaccio/commons-api';

const err = getNotFound('user not found');

callback(err);

allow_accessallow_publishallow_unpublish 回调

这些方法旨在允许或拒绝触发某些操作。

如果请求成功

如果服务能够创建用户,则返回 true 作为第二个参数。


allow_access(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
const isAllowed: boolean = checkAction(user, pkg);

callback(null, isAllowed)
}
如果请求失败

除成功之外的任何其他操作都必须返回错误。

import { getNotFound } from '@verdaccio/commons-api';

const err = getForbidden('not allowed to access package');

callback(err);

生成身份验证插件

有关详细信息,请查看我们的插件生成器页面。 在终端上运行yo命令,按照步骤操作。

➜ yo verdaccio-plugin

Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator

_-----_ ╭──────────────────────────╮
| | │ Welcome to │
|--(o)--| │ generator-verdaccio-plug │
`---------´ │ in plugin generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `

? What is the name of your plugin? service-name
? Select Language typescript
? What kind of plugin you want to create? auth
? Please, describe your plugin awesome auth plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,auth,awesome,verdaccio-plugin
create verdaccio-plugin-authservice-name/package.json
create verdaccio-plugin-authservice-name/.gitignore
create verdaccio-plugin-authservice-name/.npmignore
create verdaccio-plugin-authservice-name/jest.config.js
create verdaccio-plugin-authservice-name/.babelrc
create verdaccio-plugin-authservice-name/.travis.yml
create verdaccio-plugin-authservice-name/README.md
create verdaccio-plugin-authservice-name/.eslintrc
create verdaccio-plugin-authservice-name/.eslintignore
create verdaccio-plugin-authservice-name/src/index.ts
create verdaccio-plugin-authservice-name/index.ts
create verdaccio-plugin-authservice-name/tsconfig.json
create verdaccio-plugin-authservice-name/types/index.ts
create verdaccio-plugin-authservice-name/.editorconfig

I'm all done. 运行npm install来安装所需的依赖项。 如果失败,尝试自己运行该命令。


⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc

待安装完成,就可以访问你的项目了。

➜ cd verdaccio-plugin-service-name
➜ cat package.json

{
"name": "verdaccio-plugin-service-name",
"version": "0.0.1",
"description": "awesome auth plugin",
...

完整实现 ES5 示例

function Auth(config, stuff) {
var self = Object.create(Auth.prototype);
self._users = {};

// config for this module
self._config = config;

// verdaccio logger
self._logger = stuff.logger;

// pass verdaccio logger to ldapauth
self._config.client_options.log = stuff.logger;

return self;
}

Auth.prototype.authenticate = function (user, password, callback) {
var LdapClient = new LdapAuth(self._config.client_options);
....
LdapClient.authenticate(user, password, function (err, ldapUser) {
...
var groups;
...
callback(null, groups);
});
};

module.exports = Auth;

配置将如下所示:

auth:
htpasswd:
file: ./htpasswd

其中htpasswd是插件名称的后缀。 例如:verdaccio-htpasswd,正文的其余部分将是插件配置参数。

社区身份验证插件列表

你开发了新插件吗? 在此添加 !