strapi

strapi,Nodejs无头CMS内容管理框架,免费开源

立即访问:https://strapi.io/

strapi 是免费开源的 Nodejs 无头 CMS 内容管理框架,可以通过后台管理界面创建自定义 API,并且完全使用 JavaScript 实现
strapi官网: https://strapi.io/

主要功能
# 为 Strapi 后台管理添加单点登录
**Strapi** 是一款出色的无头内容管理系统,其后台管理系统默认支持邮箱登录。然而,由于邮箱密码账户是独立的用户系统,对于已有用户系统的组织来说,添加一套额外的用户系统既增加了管理成本,又为终端用户带来不便。因此,为 Strapi 后台管理引入单点登录方式变得极为必要。
实际上,Strapi 已经提供了单点登录特性,但需要购买许可证才能使用。在本文中,我们将探讨如何通过两个示例实现对接不同的身份提供者,一个是 Authing,另一个是其他 OIDC(OpenID Connect)提供者,如 Keycloak、Duende IdentityServer 等。
:::success
如果你只是想在测试环境验证该功能,而不愿购买许可证,可以阅读《修改 node_modules 的三种方式,隆重推荐 patch-package》一文,以在测试场景中使用完整的 Strapi 企业版功能(请勿在正式环境中使用)。
:::
本文将提供两个示例,分别是对接 Authing 和其他 OIDC 身份提供者的步骤。
## 开启 Strapi 单点登录功能
首先,假设你已经获得了 Strapi 的企业级许可证。在这种情况下,你可以轻松为 Strapi 后台管理开启单点登录功能。
然而,仅此还不够,还需要做更多的工作来适配身份源。如果你的身份源不在 Strapi 默认的身份提供者列表中,那就需要编写一些代码来进行适配。接下来的内容将为你提供在这方面的指导。
## 对接 Authing
如果你选择对接 Authing,可以通过 Authing 控制台中的单点登录(SSO)选项直接选择 Strapi,并获得一份很好的接入教程。
该教程基于 Passport 和 OAuth 2 策略,通过编写适配 Authing 的 OIDC 策略来实现。在本文中,我们将使用一个名为 “passport-authing” 的开源 Authing Passport 策略库,通过更少的代码完成对接。
在 Strapi 项目的 `config/admin.js` 文件中添加以下代码,即可完成 Strapi 与 Authing 的对接:
“`javascript
const AuthingStrategy = require(‘passport-authing’).Strategy;
module.exports = ({env}) => {
const authing = {
uid: ‘authing’,
displayName: ‘Authing’,
icon: ”,
createStrategy: (strapi) => {
return new AuthingStrategy({
domain: ‘xt1o6lgf.authing.cn’, // 从 Authing 的控制面板里复制过来
clientID: env(“AUTHING_CLIENT_ID”), // 从 Authing 的控制面板复制具体的值,建议存储在环境变量里
clientSecret: env(“AUTHING_CLIENT_SECRET”),
scope: [
“email”,
“profile”,
“openid”
],
callbackURL: strapi.admin.services.passport.getStrategyCallbackURL(
‘authing’ // 需要与上面的 provider 一致
),
}, (request, accessToken, refreshToken, profile, done) => {
done(null, {
email: profile.emails[0].value,
firstname: profile.givenName ?? profile.displayName ?? profile.emails[0].value,
lastname: profile.familyName ?? profile.nickname ?? profile.emails[0].value
})
});
}
};
return ({
auth: {
secret: env(‘ADMIN_JWT_SECRET’),
providers: [
authing
]
},
});
});
“`
## 对接其他 OIDC 提供者
接下来,我们将对接其他的 OIDC 提供者,这里以对接我部署好的 Duende IdentityServer 为例。
首先,我们需要自己编写一个 Passport OIDC 策略。以下是一个示例,演示如何添加更多的定制化功能。在这个例子中,我们添加了 IP 白名单的检查,只有在白名单内的请求才会被授权。完整代码如下:
“`javascript
const util = require(‘util’)
const OAuth2Strategy = require(‘passport-oauth2’)
const InternalOAuthError = OAuth2Strategy.InternalOAuthError
const request = require(‘request’);
function Strategy(options, verify) {
options = options || {}
options.scope = options.scope || ‘openid profile email’
this.userInfoURL = options.userInfoURL;
// 从选项中读取 IP 白名单列表
this.ipWhitelist = options.ipWhitelist ?? [];
OAuth2Strategy.call(this, options, verify)
this.name = options.provider || ‘oidc’
}
// 从 OAuth2Strategy 继承出 Strategy
util.inherits(Strategy, OAuth2Strategy)
// 记住原有的授权方法
const authenticate = Strategy.prototype.authenticate;
// 改造授权方法,以检测 IP 是否在白名单中
Strategy.prototype.authenticate = function (req, options) {
const clientIp = req.get(‘x-forwarded-for’);
if (this.ipWhitelist.indexOf(clientIp) < 0) {
throw this.fail({message: `IP 地址 ${clientIp} 不在白名单中!`});
}
return authenticate.call(this, req, options);
};
// 获取用户信息
Strategy.prototype.userProfile = function (accessToken, done) {
const self = this
const options = {
‘method’: ‘GET’,
‘url’: self.userInfoURL,
‘headers’: {
‘Authorization’: ‘Bearer ‘ + accessToken
}
};
request(options, function (err, response) {
if (err) {
return done(new InternalOAuthError(‘Failed to fetch user profile’, err))
}
try {
const json = JSON.parse(response.body)
done(null, json);
} catch (ex) {
return done(new Error(‘Failed to parse user profile’))
}
});
}
// 对外暴露策略
module.exports = {
Strategy,
}
“`
有了以上策

相关导航

没有相关内容!

暂无评论

暂无评论...