strapi官网,Nodejs無頭CMS内容管理框架,免費開源
简介
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,
}
“`
有了以上策





数据评估
本站快摸魚導航提供的strapi都来源于网络,不保证外部链接的准确性和完整性,同时,对于该外部链接的指向,不由快摸魚導航实际控制,在2023年12月20日 上午1:39收录时,该网页上的内容,都属于合规合法,后期网页的内容如出现违规,可以直接联系网站管理员进行删除,快摸魚導航不承担任何责任。
