UNPKG

cmp-mvue-toolkit

Version:
475 lines (446 loc) 14.6 kB
/** * 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); } }