Skip to main content

创建和添加自定义用户和权限提供程序

¥Creating and adding a custom Users & Permissions provider

Strapi 为 用户和权限功能 提供了 内置提供商 列表。你还可以按照本指南创建自己的提供商。

¥Strapi provides a list of built-in providers for the Users & Permissions feature. You can also create your own provider following this guide.

Prerequisites

你已阅读 用户和权限提供商文档 并了解登录流程。

¥You have read the Users & Permissions providers documentation and understood the login flow.

创建自定义提供程序

¥Creating a custom provider

你可以使用 register 生命周期函数 在 Strapi 应用的 src/index.js|ts 文件中创建自己的自定义提供程序。使用以下根据你的需要调整的代码示例:

¥You can use the register lifecycle function to create your own custom provider in the src/index.js|ts file of your Strapi application. Use the following code example adjusted to your needs:

/src/index.js
module.exports = {
register({ strapi }) {
strapi
.plugin("users-permissions")
.service("providers-registry")
.add("example-provider-name", {
icon: "",
enabled: true,
grantConfig: {
key: "",
secret: "",
callback: `${strapi.config.server.url}/auth/example-provider-name/callback`,
scope: ["email"],
authorize_url: "https://awesome.com/authorize",
access_url: "https://awesome.com/token",
oauth: 2,
},
async authCallback({ accessToken, providers, purest }) {
// use whatever you want here to get the user info
return {
username: "test",
email: "test",
};
},
});
},
};

有关传递给 grantConfig 的参数的更多信息,请参阅 `grant` 文档 。有关 purest 的更多信息,请参阅 `purest` 文档 

¥For additional information on parameters passed to grantConfig, please refer to the `grant` documentation . For additional information about purest please refer to `purest` documentation .

前端设置

¥Frontend setup

配置 Strapi 和提供程序后,你必须在前端应用中:

¥Once you have configured Strapi and the provider, in your frontend application you must:

  • 创建一个链接到 GET STRAPI_BACKEND_URL/api/connect/${provider} 的按钮(例如 https://strapi.mywebsite/api/connect/github)。

    ¥Create a button that links to GET STRAPI_BACKEND_URL/api/connect/${provider} (e.g., https://strapi.mywebsite/api/connect/github).

  • 创建一个像 FRONTEND_URL/connect/${provider}/redirect 这样的前端路由,它必须处理 access_token 参数,并且必须使用 access_token 参数请求 STRAPI_BACKEND_URL/api/auth/${provider}/callback
    JSON 请求响应将为 { "jwt": "...", "user": {...} }

    ¥Create a frontend route like FRONTEND_URL/connect/${provider}/redirect that have to handle the access_token param and that have to request STRAPI_BACKEND_URL/api/auth/${provider}/callback with the access_token parameter.
    The JSON request response will be { "jwt": "...", "user": {...} }.

现在你可以发出经过身份验证的请求,如 令牌使用 中所述。

¥Now you can make authenticated requests, as described in token usage.

故障排除
  • 错误 429:这很可能是因为你的登录流程陷入了循环。如果要向后端发出新的请求,你需要等待几分钟或重新启动后端。

    ¥Error 429: It's most likely because your login flow fell into a loop. To make new requests to the backend, you need to wait a few minutes or restart the backend.

  • 授予:缺少会话或提供程序配置错误:这可能是由于很多事情造成的。

    ¥Grant: missing session or misconfigured provider: It may be due to many things.

    • 无法构建重定向网址:确保你已在 config/server.js 中设置后端 url:设置服务器 URL

      ¥The redirect url can't be built: Make sure you have set the backend url in config/server.js: Setting up the server url

    • 会话/cookie/缓存问题:你可以在私有标签中重试。

      ¥A session/cookie/cache problem: You can try again in a private tab.

    • ngrok 域的错误使用:检查你的网址并确保你使用 ngrok 网址而不是 http://localhost:1337。不要忘记检查示例应用中 src/config.js 处设置的后端 URL。

      ¥The incorrect use of a domain with ngrok: Check your urls and make sure that you use the ngrok url instead of http://localhost:1337. Don't forget to check the backend url set in the example app at src/config.js.

  • 你无法访问你的管理面板:这很可能是因为你使用带有 ngrok url 设置的后端 url 构建它,并且你停止/重新启动了 ngrok。你需要将后端 url 替换为新的 ngrok url,并再次运行 yarn buildnpm run build

    ¥You can't access your admin panel: It's most likely because you built it with the backend url set with a ngrok url and you stopped/restarted ngrok. You need to replace the backend url with the new ngrok url and run yarn build or npm run build again.

重设密码

¥Reset password

仅适用于使用电子邮件提供者注册的用户。

¥Can only be used for users registered using the email provider.

假设的一般流程:

¥The assumed general flow:

  1. 用户转到你忘记密码的页面。

    ¥The user goes to your forgotten password page.

  2. 用户输入他们的电子邮件地址。

    ¥The user enters their email address.

  3. 你忘记密码的页面会向后端发送请求,以向用户发送包含重置密码链接的电子邮件。

    ¥Your forgotten password page sends a request to the backend to send an email with the reset password link to the user.

  4. 用户收到电子邮件并单击特殊链接。

    ¥The user receives the email and clicks on the special link.

  5. 该链接会将用户重定向到你的重置密码页面。

    ¥The link redirects the user to your reset password page.

  6. 用户输入新密码。

    ¥The user enters their new password.

  7. 重置密码页面向后端发送包含新密码的请求。

    ¥The reset password page sends a request to the backend with the new password.

  8. 如果请求包含步骤 3 链接中包含的代码,则密码将被更新。

    ¥If the request contains the code contained in the link at step 3, the password is updated.

  9. 用户可以使用新密码登录。

    ¥The user can log in with the new password.

以下部分详细介绍了步骤 3 和 7。

¥The following section details steps 3 and 7.

¥Forgotten password: ask for the reset password link

此操作会向用户发送一封电子邮件,其中包含指向你的重置密码页面的链接。该链接将使用步骤 7 中 重设密码 所需的 url 参数 code 进行丰富。

¥This action sends an email to a user with the link to your reset password page. The link will be enriched with the url param code that is needed for the reset password at step 7.

首先,你必须指定以下内容:

¥First, you must specify the following:

  • 在管理面板中:设置 > 用户和权限插件 > 高级设置 > 重置密码页面,url 为你的重置密码页面。

    ¥In the admin panel: Settings > USERS & PERMISSIONS PLUGIN > Advanced Settings > Reset Password page, the url to your reset password page.

  • 在管理面板中:设置 > 用户和权限插件 > 电子邮件模板页面,发件人电子邮件。

    ¥In the admin panel: Settings > USERS & PERMISSIONS PLUGIN > Email Template page, the Shipper email.

然后,你忘记密码的页面必须向你的后端发出以下请求:

¥Then, your forgotten password page has to make the following request to your backend:

import axios from 'axios';

// Request API.
axios
.post('http://localhost:1337/api/auth/forgot-password', {
email: 'user@strapi.io', // user's email
})
.then(response => {
console.log('Your user received an email');
})
.catch(error => {
console.log('An error occurred:', error.response);
});

重设密码:发送新密码

¥Reset Password: Send the new password

此操作将更新用户密码。这也适用于带有 resetPassword 突变的 GraphQL 插件

¥This action will update the user password. This also works with the GraphQL Plugin, with the resetPassword mutation.

你的重置密码页面必须向你的后端发出以下请求:

¥Your reset password page has to make the following request to your backend:

import axios from 'axios';

// Request API.
axios
.post('http://localhost:1337/api/auth/reset-password', {
code: 'privateCode', // code contained in the reset link of step 3.
password: 'userNewPassword',
passwordConfirmation: 'userNewPassword',
})
.then(response => {
console.log("Your user's password has been reset.");
})
.catch(error => {
console.log('An error occurred:', error.response);
});

电子邮件验证

¥Email validation

注意

在生产中,确保设置了 url 配置属性。否则验证链接将重定向到 localhost。有关配置 此处 的更多信息。

¥In production, make sure the url config property is set. Otherwise the validation link will redirect to localhost. More info on the config here.

注册后,如果你将启用电子邮件确认设置为开,用户将通过电子邮件收到确认链接。用户必须单击它来验证其注册。

¥After registering, if you have set Enable email confirmation to ON, the user will receive a confirmation link by email. The user has to click on it to validate their registration.

确认链接示例:https://yourwebsite.com/api/auth/email-confirmation?confirmation=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywiaWF0IjoxNTk0OTgxMTE3LCJleHAiOjE1OTc1NzMxMTd9.0WeB-mvuguMyr4eY8CypTZDkunR--vZYzZH6h6sChFg

¥Example of the confirmation link: https://yourwebsite.com/api/auth/email-confirmation?confirmation=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywiaWF0IjoxNTk0OTgxMTE3LCJleHAiOjE1OTc1NzMxMTd9.0WeB-mvuguMyr4eY8CypTZDkunR--vZYzZH6h6sChFg

如果需要,你可以通过提出以下请求重新发送确认电子邮件:

¥If needed you can re-send the confirmation email by making the following request:

import axios from 'axios';

// Request API.
axios
.post(`http://localhost:1337/api/auth/send-email-confirmation`, {
email: 'user@strapi.io', // user's email
})
.then(response => {
console.log('Your user received an email');
})
.catch(error => {
console.error('An error occurred:', error.response);
});

向你的 Strapi 应用添加新提供商

¥Adding a new provider to your Strapi application

信息

此文档可能与 Strapi 5 不同步,并且正在开发中。同时,非常欢迎使用 contributions 

¥This documentation might not up-to-date with Strapi 5 and is a work in progress. In the meantime, contributions  are most welcome.

授予  为许多常用的 OAuth 提供商提供配置。自定义  提供商也受支持。
你可以在此处查看和试用 200 多个受支持的提供商:OAuth Playground 

¥Grant  supplies configuration for a number of commonly used OAuth providers. Custom  providers are also supported.
You can view and try out the 200+ supported providers here: OAuth Playground .

准备你的文件

¥Prepare your files

要在 Strapi 上添加新提供商,你需要对以下文件进行更改:

¥To add a new provider on Strapi, you will need to perform changes to the following files:

extensions/users-permissions/services/Providers.js
extensions/users-permissions/config/functions/bootstrap.js

如果这些文件不存在,你将需要从 node_modules 或 Strapi mono-repo 中复制。你可以查看 插件扩展 以了解其工作原理的更多信息。

¥If these files don't exist you will need to copy from your node_modules or the Strapi mono-repo. You can see plugin extensions for more information on how it works.

我们将一步一步进行。

¥We will go step by step.

配置你的提供程序请求

¥Configure your Provider Request

getProfile 函数的 Provider.js 文件中配置新提供商。

¥Configure the new provider in the Provider.js file at the getProfile function.

getProfile 需要三个参数:

¥The getProfile takes three params:

  • 提供程序:所用提供程序的名称(字符串形式)。

    ¥provider: The name of the used provider as a string.

  • 查询:查询是提供商回调的结果。

    ¥query: The query is the result of the provider callback.

  • 回调:回调函数将继续执行内部 Strapi 登录逻辑。

    ¥callback: The callback function who will continue the internal Strapi login logic.

以下是使用 discord 提供商的示例。

¥Here is an example that uses the discord provider.

配置你的 oauth 通用信息

¥Configure your oauth generic information

case 'discord': {
const discord = new Purest({
provider: 'discord',
config: {
'discord': {
'https://discordapp.com/api/': {
'__domain': {
'auth': {
'auth': {'bearer': '[0]'}
}
},
'{endpoint}': {
'__path': {
'alias': '__default'
}
}
}
}
}
});
}

此代码创建一个 Purest 对象,为我们提供了一种与提供商的 REST API 交互的通用方法。

¥This code creates a Purest object that gives us a generic way to interact with the provider's REST API.

有关使用 Purest 模块的更多规范,请参阅官方 Purest 文档 

¥For more specs on using the Purest module, please refer to the Official Purest Documentation 

你可能还想查看大量已完成的配置 此处 

¥You may also want to take a look onto the numerous already made configurations here .

检索你的用户信息

¥Retrieve your user's information

对于我们的 Discord 提供商,它将如下所示:

¥For our Discord provider it will look like the following:

  discord.query().get('users/@me').auth(access_token).request((err, res, body) => {
if (err) {
callback(err);
} else {
// Combine username and discriminator because discord username is not unique
const username = `${body.username}#${body.discriminator}`;
callback(null, {
username,
email: body.email
});
}
});
break;
}

这是我们切换的下一部分。现在我们已经正确配置了我们的提供程序,我们想使用它来检索用户信息。

¥Here is the next part of our switch. Now that we have properly configured our provider, we want to use it to retrieve user information.

在这里你可以看到 purest 的真正威力,你可以简单地对所需的 URL 发出 get 请求,使用 query 参数中的 access_token 进行身份验证。

¥Here you see the real power of purest, you can simply make a get request on the desired URL, using the access_token from the query parameter to authenticate.

这样,你应该能够检索所需的用户信息。

¥That way, you should be able to retrieve the user info you need.

现在,你只需使用用户的用户名和电子邮件调用 callback 函数即可。这样,Strapi 将能够从数据库中检索你的用户并让你登录。

¥Now, you can simply call the callback function with the username and email of your user. That way, Strapi will be able to retrieve your user from the database and log you in.

将新的提供程序模型配置到数据库中

¥Configure the new provider model onto database

现在,我们需要为我们的新提供商配置我们的 'model'。这样,我们的设置就可以存储在数据库中,并从管理面板进行管理。

¥Now, we need to configure our 'model' for our new provider. That way, our settings can be stored in the database, and managed from the admin panel.

打开文件 packages/strapi-plugin-users-permissions/config/functions/bootstrap.js

¥Open the file packages/strapi-plugin-users-permissions/config/functions/bootstrap.js

将提供商需要的字段添加到 grantConfig 对象中。对于我们的 discord 提供商,它将如下所示:

¥Add the fields your provider needs into the grantConfig object. For our discord provider it will look like:

discord: {
enabled: false, // make this provider disabled by default
icon: 'comments', // The icon to use on the UI
key: '', // our provider app id (leave it blank, you will fill it with the Content Manager)
secret: '', // our provider secret key (leave it blank, you will fill it with the Content Manager)
callback: '/auth/discord/callback', // the callback endpoint of our provider
scope: [ // the scope that we need from our user to retrieve information
'identify',
'email'
]
},