cmp-mvue-toolkit
Version:
mvue project toolkit components
475 lines (446 loc) • 14.6 kB
JavaScript
/**
* SSO客户端
*/
import _ from "../tools/lodash_loader";
var utils=require('../utils').default;
var Config=require("../../config/config.js");
var Base64=require("js-base64").Base64;
var http=require("axios");
var qs=require("qs");
/**
* 跳转到sso登录页面
*/
function gotoLogin(returnUrl,session) {
var params=resolveParams(window.location.href)||{};
var state=params["state"];
var domain=window.location.protocol+"//"+window.location.host;
if(window.location.port&&domain.indexOf(window.location.port)<0)
domain+=":"+window.location.port;
if(state&&state!="/"){
var lastChar=state.charAt(state.length-1);
if(lastChar=="/") {
state = state.substring(0, state.length - 1)
}
if(lastChar=="#") {
state = state.substring(0, state.length - 1)
}
returnUrl=state;
}
var ssoclientUrl = domain;
ssoclientUrl +="/static/ssoclient.html?returnUrl=" + encodeURIComponent(returnUrl);
var url = gotoLoginUrl(ssoclientUrl);
url+="&raw_return_url="+encodeURIComponent(returnUrl);
if(url.charAt(0)=="#"){
return {path:url.substring(1)};
}
if(parent && utils.getWebContext()!="/"){
console.log("reload parent,returnUrl:" + returnUrl);
parent.location.reload();
return;
}
window.location = url;
}
function gotoLoginUrl(ssoclientUrl) {
var url = "";
if (Config.isLocalLogin()) {
url = buildLoginUrlForLocal(ssoclientUrl);
if(!url){
console.error('SSO基础地址为空');
return;
}
} else if (Config.getSSOVersion() == "v2") {
url = buildLoginUrlForV2(ssoclientUrl);
if(!url){
console.error('SSO基础地址为空');
return;
}
} else {
url = buildLoginUrlForV3(ssoclientUrl);
if(!url){
console.error('SSO基础地址为空');
return;
}
if (Config.getOAuth2FlowType() == "implicit") {
url += "&response_type=token";
} else if (Config.getOAuth2FlowType() == "accessCode") {
url += "&response_type=code";
} else {
url += "&response_type=" + encodeURIComponent("code id_token");
}
}
if(!url){
alert("未配置配置地址");
throw "未配置配置地址";
}
return url;
}
function buildLoginUrlForLocal(returnUrl) {
var url=Config.getLocalLoginUrl();
if(!url){
return null;
}
return `${url}?return_url=${encodeURIComponent(returnUrl)}`;
}
function buildLoginUrlForV2(returnUrl){
var url=Config.getSSOServerUrl();
if(!url){
return null;
}
url+="/v2?openid.mode=checkid_setup&openid.ex.client_id="+(Config.getClientId()||"clientId");
url+="&openid.return_to="+encodeURIComponent(returnUrl);
return url;
}
function buildLoginUrlForV3(returnUrl) {
let url = Config.getSSOAuthorizeUrl();
if (!url) {
url = Config.getSSOServerUrl();
if (!url) {
return null;
}
url += "/oauth2/authorize";
}
if(url.charAt(0)=="#"){
returnUrl=returnUrl.substring(returnUrl.indexOf("#"));
}
url += "?client_id=" + Config.getClientId();
url += "&redirect_uri=" + encodeURIComponent(returnUrl);
url += "&logout_uri=" + encodeURIComponent(window.location.protocol + "//" + window.location.host + window.location.pathname + "?_d=" + new Date().valueOf() + "#/ssoclient?logout=1&_inframe=true");
return url;
}
/**
* 处理sso回调
*/
function onSSOCallback(callback) {
if (Config.isLocalLogin()) {
return processCallbackLocal(callback);
}
if (Config.getSSOVersion() == "v2") {
return processCallbackForV2(callback);
}
return processCallbackForV3(callback);
}
/**
* 本地登录成功后的处理
* @param callback
* @returns {Promise<any>}
*/
function processCallbackLocal(callback) {
var url = Config.getLocalUserInfoUrl() + "?_=" + new Date().getTime();
return new Promise(function (resolve, reject) {
http.get(url).then(function ({data}) {
var tokenInfo = {
user: {},
mode:"local"
};
var user = _.assign({}, data, {anonymous: false});
tokenInfo["user"] = user;
if (callback) {
callback(tokenInfo);
}
resolve(tokenInfo);
}).catch(function (error) {
reject(null);
});
});
}
/**
* v2流程校验serviceticket,获取access_token
* @param callback
*/
function processCallbackForV2(callback) {
var params = resolveParams(window.location.href) || {};
var ticket = params["openid.ex.service_ticket"];
var tokenUrl = Config.getSSOServerUrl() + "/v2";
var reqParam = {
"openid.mode": "check_authentication",
"openid.ex.client_id": Config.getClientId(),
"openid.ex.client_secret": Config.getClientSecret(),
"openid.ex.service_ticke": ticket,
"openid.ex.logout_url": window.location.href + "#/logout",
"openid.ex.get_oauth_access_token": "y"
};
http.post(tokenUrl, qs.stringify(reqParam), {"responseType": "text"})
.then(function ({data}) {
var arrItems = data.replace(/\r/g, "").split("\\n");
var respMap = {};
_.forEach(arrItems, function (item, index) {
if (_.isEmpty(item)) {
return;
}
var entry = item.split(":");
if (entry.length != 2) {
return;
}
respMap[entry[0]] = entry[1];
})
if (respMap["mode"] != "ok") {
console.error("ticket " + ticket + " 无效,错误信息:" + respMap["error"]);
return;
}
var tokenInfo = {
accessToken: respMap["ex.oauth_access_token"],
identity: respMap["identity"],
expiresIn: token["ex.oauth_access_token_expires"],
refreshToken: token["ex.oauth_refresh_token"],
user:{
name: respMap["identity"],
userId: respMap["identity"]
},
mode:"v2"
};
if (callback) {
callback(tokenInfo);
}
}).catch(function (error) {
console.log(error.response.data);
});
}
/**
* v3版SSO回调 ,验证accessCode获取access_token
* @param callback
*/
function processCallbackForV3(callback){
if(Config.getOAuth2FlowType()=="implicit"){
return onImplictFlow(callback);
}else{
return onAccessCodeFlow(callback);
}
}
/**
* 处理隐式流程
* @param callback
*/
function onImplictFlow(callback){
var params=resolveParams(window.location.href)||{};
var tokenInfo={
accessToken:params["access_token"],
expiresIn:params["expires_in"],
state:params["state"],
mode:"v3",
modeMore:{
flowType:"implicit"
}
};
getUserInfo(tokenInfo).then(function (userInfo) {
if(callback){
callback(tokenInfo);
}
});
}
function checkAccessCode(accessCode,callback) {
var tokenUrl = Config.getSSOTokenUrl();
var basicAuth = getClientAuth();
var heads={'Authorization': basicAuth};
if(!tokenUrl)
tokenUrl = Config.getSSOServerUrl() + "/oauth2/token";
else{
heads["Content-Type"]="application/x-www-form-urlencoded";
}
var reqParam = {
"grant_type": "authorization_code",
"code": accessCode,
"client_id":Config.getClientId(),
"client_secret":Config.getClientSecret(),
"redirect_uri":document.referrer.replace("&code="+accessCode,"")
};
var result=1;
http.post(tokenUrl, qs.stringify(reqParam), {headers: heads})
.then(function ({data}) {
if (callback) {
callback(data);
}
}).catch(function (error) {
if (error.response && error.response.data) {
console.log(error.response.data);
alert("从‘统一认证中心系统’获取token异常,请联系统一认证中心相关人员,异常信息如下:" + JSON.stringify(error.response.data));
result = 0;
}
});
return result;
}
function getUserInfo(tokenInfo) {
//用户地址
var url= Config.getSSOUserinfoUrl();
var authorization=tokenInfo.tokenId;
if(!url)
url = Config.getSSOServerUrl()+"/oauth2/userinfo";
if(url.indexOf("http")!=0){
var domain=window.location.protocol+"//"+window.location.host;
if(window.location.port&&domain.indexOf(window.location.port)<0)
domain+=":"+window.location.port;
if(url.indexOf("/")!=0)
domain+="/";
url=domain+url;
}
if(url.indexOf("?")<0)
url+="?";
url += "_="+new Date().getTime();
return new Promise(function (resolve,reject) {
http.get(url,{"headers":{"Authorization":"Bearer "+authorization}})
.then(function ({data}) {
var username=data["name"] || data["username"];
if(data["sub"]&&data["sub"].indexOf("@")>-1)
username=username+"/"+data["sub"].split("@")[0];
var user=_.assign({},data,{
name:username,
userId:data["sub"]||data["yst_id"],
anonymous:false
});
tokenInfo["user"]=user;
resolve(user);
}).catch(function (error) {
getUserInfoError(error,tokenInfo);
});
});
}
function getUserInfoError(error,tokenInfo) {
var infoStr="登录统一认证中心的用户在云平台中不存在";
if(error.response&&error.response.data){
infoStr = error.response.data.error_description;
}
infoStr+=",请重新登录或联系统一认证中心相关人员!";
var domain=window.location.protocol+"//"+window.location.host;
if(window.location.port&&domain.indexOf(window.location.port)<0)
domain+=":"+window.location.port;
var params=resolveParams(window.location.href)||{};
var returnUrl=params["returnUrl"];
window.location=domain+"/#/notUser?message=" + infoStr+"&returnUrl="+encodeURIComponent(returnUrl)+"&tokenId="+tokenInfo.tokenId;
}
/**
* 处理授权码流程
* @param callback
*/
function onAccessCodeFlow(callback) {
var params=resolveParams(window.location.href)||{};
var code=params["code"];
var result = checkAccessCode(code,function (token) {
var tokenInfo={
accessToken:token["access_token"],
expiresIn:token["expires_in"],
state:token["state"],
tokenId:token["id_token"]||token["access_token"],
refreshToken:token["refresh_token"],
mode:"v3",
modeMore:{
flowType:"accessCode"
}
};
if(result==0){
return;
}
getUserInfo(tokenInfo).then(function (userInfo) {
if(callback){
callback(tokenInfo);
}
});
});
}
function refreshToken(tokenInfo,callback) {
var tokenUrl = Config.getSSOTokenUrl();
var basicAuth = getClientAuth();
var heads={'Authorization': basicAuth};
if(!tokenUrl)
tokenUrl = Config.getSSOServerUrl() + "/oauth2/token";
else{
heads["Content-Type"]="application/x-www-form-urlencoded";
}
var reqParam = {
"grant_type": "refresh_token",
"refresh_token": tokenInfo.refreshToken,
"client_id":Config.getClientId(),
"client_secret":Config.getClientSecret()
};
http.post(tokenUrl, qs.stringify(reqParam), {headers: heads})
.then(function ({data}) {
if (callback&&data) {
var newtokenInfo={
accessToken:data["access_token"],
expiresIn:data["expires_in"],
state:data["state"],
tokenId:data["id_token"]||data["access_token"],
refreshToken:data["refresh_token"],
mode:"v3",
modeMore:{
flowType:"accessCode"
}
};
newtokenInfo["user"]=tokenInfo["user"];
callback(newtokenInfo);
}
}).catch(function (error) {
console.log(error.message);
});
}
function resolveParams(url) {
if(!url) return;
url = url + '';
var index = url.indexOf('?');
if(index > -1) {
url = url.substring(index + 1, url.length);
}
var pairs = url.split('&'), params = {};
for(var i = 0; i < pairs.length; i++) {
var pair = pairs[i];
var indexEq = pair.indexOf('='), key = pair, value = null;
if(indexEq > 0) {
key = pair.substring(0, indexEq);
value = decodeURIComponent(pair.substring(indexEq + 1, pair.length));
}
params[key] = value;
}
return params;
}
function getClientAuth() {
var clientId=Config.getClientId();
var clientSecret=Config.getClientSecret();
return "Basic "+Base64.encode(clientId+":"+clientSecret);
}
function ssoLogout(returnUrl,token) {
var url = "";
if (Config.isLocalLogin()) {
url = Config.getLocalLogoutUrl() + "?return_url=" + encodeURIComponent(returnUrl);
window.location = url;
return;
}
url = Config.getSSOLogoutUrl();
if (!url) {
url = Config.getSSOServerUrl();
if (Config.getSSOVersion() == "v2") {
url += "/v2?openid.mode=logout";
url += "&openid.return_to=" + encodeURIComponent(returnUrl);
} else {
url += "/oauth2/logout?post_logout_redirect_uri=" + encodeURIComponent(returnUrl);
}
window.location = url;
return;
}
var domain = window.location.protocol + "//" + window.location.host;
if (window.location.port && domain.indexOf(window.location.port) < 0)
domain += ":" + window.location.port;
if (token && token.tokenId) {
url += "?id_token_hint=" + token.tokenId + "&post_logout_redirect_uri=" + encodeURIComponent(domain);
if (returnUrl) {
url += "&state=" + encodeURIComponent(returnUrl);
}
} else {
url = domain;
}
window.location = url;
}
export default {
gotoLogin: function (returnUrl,session) {
return gotoLogin(returnUrl,session);
},
onSSOCallback: function (callback) {
onSSOCallback(callback);
},
refreshToken: function (tokenInfo,callback) {
refreshToken(tokenInfo,callback);
},
ssoLogout: function (returnUrl,token) {
ssoLogout(returnUrl,token);
},
resolveParams: function (url) {
return resolveParams(url);
}
}