问题:发现此插件对我们使用的sso服务器不匹配,无法登录成功YApi,结合yapi-plugin-qsso插件对yapi-plugin-cas做了代码修改。
经验:根据不同公司sso或cas服务器及验证方式或参数名不同,插件使用方式(或代码)可能需要做不同调整。改完登录截图如下:
具体修改说明如下。
一、此处使用的sso登录地址类似如下,前面是要使用sso服务器网址,ref后面是yapi的登录地址:
https://login.sso.test.com/login?ref=http://yapi.yourdomain.com:3000
另外,登录后yapi需要从sso服务器获取用户信息的网址类似如下,sid是登录成功后sso返回的固定参数,但每次参数值不一样,一次有效,过期也失效:
https://login.sso.test.com/login?ref=http://yapi.yourdomain.com:3000&sid=123dgrcvshjgrhtdvjdfhjgjko
访问sso登录地址,获取用户信息后的结果举例,当前主要使用了user: {"mail": "lixiaoming@163.com", "memberOf": "CN=yourgg,OU=MailGroups,DC=test,DC=163,DC=com", "user": "lixiaoming", "display": "李晓明"}
二、yapi的config.json修改类似如下:
"plugins": [
{
"name": "cas",
"options": {
"type": "cas",
"LOGIN_SERVER": "https://login.sso.test.com/login?ref=",
"emailPostfix": "@your.cn",
"AUTH_SERVER": "https://login.sso.test.com/login?ref="
}
}
]
三、yapi-plugin-cas/client.js代码修改完如下:
import React, { Component } from 'react'
const qualifyURL = (url, encode) => {
url = url || '';
let ret = location.protocol + '//' + location.host + (url.substr(0, 1) === '/' ? '' : location.pathname.match(/.*\//)) + url;
if (encode) {
ret = encodeURIComponent(ret);
}
return ret;
}
module.exports = function (options) {
const handleLogin = () => {
const loginURI = '/api/user/login_by_token';
const { LOGIN_SERVER } = options;
let ret = qualifyURL(loginURI, true);
let redirectURL = LOGIN_SERVER + ret;
location.href = redirectURL;
}
const WSComponent = () => (
<button onClick={handleLogin} className="btn-home btn-home-normal" >SSO 域账号登录</button>
)
this.bindHook('third_login', WSComponent);
}
四、server.js代码修改完如下:
const request = require('request');
const parseString = require('xml2js').parseString;
module.exports = function (options) {
const { AUTH_SERVER, emailPostfix } = options
this.bindHook('third_login', (ctx) => {
let ticket = ctx.request.body.sid || ctx.request.query.sid;
let requestUrl = ctx.request.protocol + '://' + ctx.request.host + ctx.request.path;
let validateUrl = AUTH_SERVER + encodeURIComponent(requestUrl) + '&sid=' + ticket;
return new Promise((resolve, reject) => {
// console.log('cas url:',validateUrl);
request.get(validateUrl, function(error, response, body) {
if (!error && response.statusCode == 200) {
let result = JSON.parse(body);
if (result && result.user ) {
let ret = {
email: result.user + emailPostfix,
username: result.user
};
resolve(ret);
// console.log('cas ret :',ret);
} else {
reject(result);
// console.log('cas res er:',result);
}
} else {
reject(error);
// console.log('cas get er:',error);
}
})
})
});
}
五、注意事项 虽然修改js代码有些是即时生效的,但是这个插件里会有一些静态资源,而我直接使用的“生产环境”启动方式,所以改完代码后需要按如下执行重新编译(ykit也是开源命令,如果没有需自行安装)。
cd vendors
编译:
ykit pack -m
重新启动服务:
node server/app.js
六、相关主要参考资料链接
源码
https://github.com/wsfe/yapi-plugin-cas
https://github.com/YMFE/yapi-plugin-qsso
React教程
https://www.runoob.com/react/react-tutorial.html
YApi官档
https://hellosean1025.github.io/yapi/devops/index.html
七、最后再推荐一个代码搜索命令ack,linux下可以直接yum安装:yum install ack 使用举例,以关键字“koa”搜索.js文件(--js),忽略大小写(-i),忽略static目录: ack --js "koa" -i --ignore-dir=static