提供程序为插件的核心功能添加了扩展,例如将媒体文件上传到 AWS S3 而不是本地服务器,或使用 Amazon SES 而不是 Sendmail 发送电子邮件。
对于相关插件,Strapi 维护的官方提供程序(可通过 Marketplace 发现)和许多社区维护的提供程序可通过 npm 获取。
可以将提供程序配置为 private,以确保资产 URL 将被签名以实现安全访问。
安装提供程序
可以使用 npm
或 yarn
安装新的提供程序,格式为 @strapi/provider-<plugin>-<provider> --save
。
例如:
#为上传插件安装 AWS S3 提供程序
yarn add @strapi/provider-upload-aws-s3
#为电子邮件插件安装 Sendgrid 提供程序
yarn add @strapi/provider-email-sendgrid --save
配置提供程序
新安装的提供程序在 ./config/plugins.js
文件中启用和配置。如果此文件不存在,则必须创建它。
每个提供程序都有不同的配置设置可用。查看 Marketplace 或 npm 中该提供商的相应条目以了解更多信息。
以下是上传和电子邮件插件的示例配置。
Upload
module.exports = ({ env }) => ({
// ...
upload: {
config: {
provider: 'aws-s3', // 对于社区提供商,传递完整的包名称(例如提供商:“strapi-provider-upload-google-cloud-storage”)
providerOptions: {
accessKeyId: env('AWS_ACCESS_KEY_ID'),
secretAccessKey: env('AWS_ACCESS_SECRET'),
region: env('AWS_REGION'),
params: {
ACL: env('AWS_ACL', 'public-read'), // 'private' 如果你想将上传的文件设为私密
Bucket: env('AWS_BUCKET'),
},
},
},
},
// ...
})
Strapi 有一个默认的 security
中间件,它有一个非常严格的 contentSecurityPolicy
,将图像和媒体的加载限制为仅 "'self'"
,有关更多信息,请参阅 provider 页面 上的示例配置或 中间件文档。
module.exports = ({ env }) => ({
// ...
email: {
config: {
provider: 'sendgrid', // 对于社区提供商,传递完整的包名称(例如提供商:“strapi-provider-email-mandrill”)
providerOptions: {
apiKey: env('SENDGRID_API_KEY'),
},
settings: {
defaultFrom: 'juliasedefdjian@strapi.io',
defaultReplyTo: 'juliasedefdjian@strapi.io',
testAddress: 'juliasedefdjian@strapi.io',
},
},
},
// ...
})
如果您更喜欢使用 Sendmail 而不是 Sendgrid,请参阅 @strapi/provider-email-sendmail
文档。
每个环境的配置
配置提供程序时,您可能希望根据 NODE_ENV
环境变量更改配置或使用特定于环境的凭据。
您可以在 ./config/env/{env}/plugins.js
配置文件中设置特定配置,它将用于覆盖默认配置。
创建提供程序
要实现您自己的自定义提供程序,您必须创建一个 Node.js 模块。
必须导出的接口取决于您正在为其开发提供程序的插件。以下是上传和电子邮件插件的模板:
Upload
module.exports = {
init(providerOptions) {
// init your provider if necessary
return {
upload(file) {
// upload the file in the provider
// file content is accessible by `file.buffer`
},
uploadStream(file) {
// upload the file in the provider
// file content is accessible by `file.stream`
},
delete(file) {
// delete the file in the provider
},
checkFileSize(file, { sizeLimit }) {
// (optional)
// implement your own file size limit logic
},
getSignedUrl(file) {
// (optional)
// Generate a signed URL for the given file.
// The signed URL allows secure access to the file.
// Only Content Manager assets will be signed.
// Returns an object {url: string}.
},
isPrivate() {
// (optional)
// if it is private, file urls will be signed
// Returns a boolean
},
}
},
}
module.exports = {
init: (providerOptions = {}, settings = {}) => {
return {
send: async (options) => {},
}
},
}
在发送函数中,您将可以访问:
- 包含用
plugins.js
编写的配置的providerOptions
- 包含用
plugins.js
编写的配置的settings
- 包含从电子邮件插件服务调用发送函数时发送的选项的
options
您可以查看 Strapi 维护的提供程序 以获取示例实现。
创建新提供程序后,您可以 将其发布到 npm 与社区共享或 在本地使用它 仅用于您的项目。
本地提供程序
如果您想创建自己的提供程序而不将其发布在 npm 上,您可以按照以下步骤操作:
- 在您的应用程序中创建一个
providers
文件夹。 - 创建您的提供程序(例如
./providers/strapi-provider-<plugin>-<provider>
) - 然后更新您的
package.json
,将您的strapi-provider-<plugin>-<provider>
依赖项链接到新提供程序的 本地路径。json{ // ... "dependencies": { // ... "strapi-provider-<plugin>-<provider>": "file:providers/strapi-provider-<plugin>-<provider>" // ... } }
- 更新您的
./config/plugins.js
文件以 配置提供程序。 - 最后,运行
yarn install
或npm install
来安装您的新自定义提供程序。
创建私有提供程序
您可以设置私有提供程序,这意味着内容管理器中显示的每个资产 URL 都将被签名以实现安全访问。
要启用私有提供程序,您必须实现 isPrivate()
方法并返回 true
。
在后端,Strapi 使用提供程序中实现的 getSignedUrl(file)
方法为每个资产生成一个签名 URL。签名 URL 包含一个加密签名,允许用户访问资产(但通常仅在有限的时间内并有特定限制,具体取决于提供程序)。
请注意,出于安全原因,内容 API 不会提供任何签名 URL。相反,使用该 API 的开发人员应该自己对 URL 进行签名。
示例
要创建私有 aws-s3
提供程序:
- 在您的应用程序中创建一个
./providers/aws-s3
文件夹。有关更多信息,请参阅 本地提供程序。 - 在
aws-s3
提供程序中实现isPrivate()
方法以返回true
。 - 在
aws-s3
提供程序中实现getSignedUrl(file)
方法以生成给定文件的签名 URL。
// aws-s3 provider
module.exports = {
init: (config) => {
const s3 = new AWS.S3(config)
return {
async upload(file) {
// code to upload file to S3
},
async delete(file) {
// code to delete file from S3
},
async isPrivate() {
return true
},
async getSignedUrl(file) {
const params = {
Bucket: config.params.Bucket,
Key: file.path,
Expires: 60, // URL expiration time in seconds
}
const signedUrl = await s3.getSignedUrlPromise('getObject', params)
return { url: signedUrl }
},
}
},
}