电脑桌面
添加蚂蚁七词文库到电脑桌面
安装后可以在桌面快捷访问

苍穹应用菜单触发 | 在新浏览器窗口打开第三方带会话信息页面

来源:金蝶云社区作者:金蝶2024-09-234

苍穹应用菜单触发 | 在新浏览器窗口打开第三方带会话信息页面

# 关键词:单点登录、页面集成、页面跳转、应用菜单点击、新浏览器窗口 # 一、需求 苍穹与第三方系统进行集成。用户登录苍穹之后,在应用首页点击某个菜单之后,系统自动单点登录并以新的浏览器窗口打开第三方系统的指定页面,然后用户可自由进行业务操作。此外,需补充说明的是,第三方系统不支持身份认证功能,而本案例需求涉及到单点登录功能,故需要有一个用作统一身份认证服务的系统。 # 二、思路与方案 本案例需求的关键点包含2点:第一,用户点击应用菜单实现跳转到第三方系统;第二,苍穹跳转第三方系统页面时需支持单点登录。 首先,关于第二点,考虑到第三方系统不支持身份认证功能,故需要借助一个统一身份认证系统来实现苍穹与第三方系统的单点登录,但前提需使苍穹、第三方系统、统一身份认证服务系统之间的用户数据保持一致。关于该点功能开发,社区已存在丰富资料,可自行查阅参考开发。 其次,第一点的难点在于需要在用户点击应用菜单时进行干预,但我们不清楚该从哪里入手去进行二开。这里,我们进入应用首页后,在菜单位置点击鼠标,通过快捷键 **ctrl+alt+g** 进入鼠标焦点所在的应用首页的设计器界面,然后通过表单上注册的插件 BizAppHomePlugin 的事件 treeMenuClick(TreeNodeEvent) 分析可知:苍穹应用菜单上必须配置待打开的页面才行。但考虑到我们是需要打开第三方系统的页面,在苍穹系统里面并没有,故可开发一个空白动态表单页面,并将其配置应用菜单上,然后在用户点击应用菜单的时候取消打开该动态表单,转而通过重写纵向导航栏控件的 treeMenuClick(TreeNodeEvent) 事件来实现跳转第三方系统页面。 # 三、实现过程 ## 3.1 准备工作 苍穹系统:http://172.20.14.30:8080/ierp 第三方系统:本案例以另一套苍穹环境进行模拟,其访问地址:http://172.20.240.88:8080/ierp 统一身份认证服务系统:https://api.kingdee.com ## 3.2 注册应用 登录[金蝶云平台](https://cloud.kingdee.com/)注册应用,设置回调地址为苍穹系统的IP&端口,用于苍穹系统登录认证 *备注: 如需复现案例效果,请自行前往金蝶云平台注册应用后,配置回调地址,并修改 Parameter.java & CloudPlatformSSOAuth.java 文件中 CLIENT_ID & CLIENT_SECRET 的值。* ![云平台应用-苍穹.webp](/download/0100d98fa9f344ab4bbea99e2e0e8dbdc0e0.webp) ## 3.3 在苍穹系统中开发单点登录金蝶云平台插件(CldPlatformSSOPlugin) 1.先判断系统是否登录,若没有,则返回;若已登录,则根据金蝶云平台返回的授权码获取access_token,再获取用户信息进行认证,认证成功则登录苍穹系统。 ```language @Override public UserAuthResult getTrdSSOAuth(HttpServletRequest request, HttpServletResponse response) { UserAuthResult result = new UserAuthResult(); result.setSucess(false); // 判断是否成功登录金蝶云平台, 通过code进行判断 String code = request.getParameter("code"); String state = request.getParameter("state"); if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) { result.setErrDesc("单点登录失败"); return result; } // 获取构造缓存 DistributeSessionlessCache cache = CacheFactory.getCommonCacheFactory().getDistributeSessionlessCache(KEY_CACHE_SSOLOGIN); String infoStr = cache.get(state); JSONObject paramObj; if (StringUtils.isNotEmpty(infoStr)) { paramObj = JSONObject.parseObject(infoStr); } else { paramObj = new JSONObject(); } // 重定向到指定页面 String queryParam = paramObj.getString("queryparam"); if (!request.getQueryString().contains("flag=1")) { try { String url = String.format("%1$s/?code=%2$s&state=%3$s&flag=1", Parameter.COSMIC_HOME_URL, code, URLEncoder.encode(state, "UTF-8")); if (StringUtils.isNotEmpty(queryParam)) { url = String.format("%1$s&%2$s", url, queryParam); } response.sendRedirect(url); } catch (Exception e) { logger.error(String.format("重定向失败: %s", ExceptionUtils.getExceptionStackTraceMessage(e))); } return result; } // 从云平台获取access_token JSONObject responseObj = SSOUtil.getAccessToken(code); Integer errCode = responseObj.getInteger("errcode"); String accessToken = null; if (errCode != null && errCode == 0) { accessToken = responseObj.getJSONObject("data").getString("access_token"); request.setAttribute("kdcloudaccesstoken", accessToken); } else { String errDesc = StringUtils.isEmpty(responseObj.getString("description")) ? "未获取到access_token信息!" : responseObj.getString("description"); result.setErrDesc(errDesc); logger.error(errDesc); return result; } // 从云平台获取登录用户基本信息 JSONObject userInfoObj = SSOUtil.getUserInfo(accessToken); errCode = userInfoObj.getInteger("errcode"); if (errCode != null && errCode == 0) { JSONObject data = userInfoObj.getJSONObject("data"); result.setUser(data.getString("phone")); result.setUserType(UserProperType.Mobile); result.setSucess(true); } else { String errDesc = StringUtils.isEmpty(userInfoObj.getString("description")) ? "未查询到用户信息!" : userInfoObj.getString("description"); logger.error(errDesc); throw new KDException(LoginErrorCode.loginBizException, "系统错误,请联系系统管理员。" + errDesc); } return result; } ``` 2.若用户未登录,则跳转到金蝶云平台的登录页,成功登陆之后系统重定向到苍穹系统门户首页。若用户退出系统、或者再次访问之前已登录的地址,则通过重定向到苍穹默认登录页转而重定向到金蝶云平台的登录页 ```language @Override public void callTrdSSOLogin(HttpServletRequest request, HttpServletResponse response, String backUrl) { // 退出处理 if (request.getRequestURI().contains("logout.do")) { this.logout(request); this.sendRedirect(response, Parameter.COSMIC_HOME_URL); return; } if (!response.isCommitted()) { // 用户未登录, 且访问链接包含以前请求的code & state 参数, 则重定向到本系统的homeUrl发起访问 String code = request.getParameter("code"); String state = request.getParameter("state"); if (StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(state)) { this.sendRedirect(response, Parameter.COSMIC_HOME_URL); return; } } // sso插件重定向处理 if (request.getQueryString() != null && request.getQueryString().contains("flag=1")) { return; } // 正常登录访问苍穹,构造缓存数据 String state = ID.genStringId(); DistributeSessionlessCache cache = CacheFactory.getCommonCacheFactory().getDistributeSessionlessCache(KEY_CACHE_SSOLOGIN); JSONObject paramObj = new JSONObject(); paramObj.put("queryparam", request.getQueryString()); cache.put(state, JSONObject.toJSONString(paramObj), 60); // 根据sso地址构造,登录地址 重定向到云平台 try { // 成功登录之后重定向到系统门户首页 String redirectUri = String.format("%1$s%2$s", SSOUtil.getHomeUrl(Parameter.COSMIC_HOME_URL), "index.html"); String url = String.format("%1$s?client_id=%2$s&response_type=%3$s&redirect_uri=%4$s&state=%5$s", String.format("%1$s%2$s", SSOUtil.getHomeUrl(Parameter.AUTH_CENTER_URL), "auth/oauth2/authorize"), Parameter.CLIENT_ID, "code", URLEncoder.encode(redirectUri, "UTF-8"), URLEncoder.encode(state, "UTF-8")); response.sendRedirect(url); } catch (IOException e) { logger.error(String.format("重定向失败: %s", ExceptionUtils.getExceptionStackTraceMessage(e))); } } ``` 3.成功登陆之后,将 access_token 放入分布式缓存中,后续在跳转第三方系统页面时使用 ```language @Override public void processSucceedLogin(HttpServletRequest request, String globalSessionId) { // 将从金蝶云平台获取的 access_token 存入分布式缓存, 1天有效期. 后续跳转第三方系统页面时取出使用 String accessToken = (String) request.getAttribute("kdcloudaccesstoken"); DistributeSessionlessCache cache = CacheFactory.getCommonCacheFactory().getDistributeSessionlessCache(KEY_CACHE_SSOLOGIN); cache.put(globalSessionId, "kdcloudaccesstoken", accessToken, 1 * 24 * 60 * 60); ThirdSSOAuthHandler.super.processSucceedLogin(request, globalSessionId); } ``` ## 3.4 配置应用菜单(ToTrdSysPageFormPlugin) *备注: 当用户点击应用菜单后,会触发应用首页上默认注册的插件 BizAppHomePlugin,并执行 treeMenuClick(TreeNodeEvent) 方法。分析该方法代码可知:应用菜单必须绑定一个苍穹平台内的页面才能实现在点击菜单后跳转对应页面。* *因此,我们可考虑通过为菜单绑定一个空白动态表单,然后在点击应用菜单的时候取消打开该表单页面,转而通过重写应用首页上纵向导航栏控件的 treeMenuClick(TreeNodeEvent) 事件来实现跳转第三方系统页面。* *其次,由于不能通过该方法提供的接口setCancel(true)去取消打开表单页面,故只能在表单页面上注册插件来进行取消。* ### 1.开发空白动态表单,其表单设计器如图所示 ![kdec_totrdpagebyappmenu.webp](/download/0100f2040ce973124353a70c17820b7a1c81.webp) ### 2.在上述页面注册插件取消其打开(kdec_totrdpagebyappmenu) ```language @Override public void preOpenForm(PreOpenFormEventArgs e) { // 取消打开页面 e.setCancel(true); super.preOpenForm(e); } ``` ### 3.菜单配置 ![菜单跳转1-菜单配置.webp](/download/010049cf734884bd4c8d8f8d0abbb56c028a.webp) ## 3.5 在应用首页上注册插件二开干预应用菜单的点击事件(CustomBizAppHomePlugin2) ```language @Override public void treeMenuClick(TreeNodeEvent evt) { // 点击指定菜单跳转第三方系统页面 Object appMenuNodeId = evt.getNodeId(); AppMenuInfo appMenuInfo = AppMetadataCache.getAppMenuInfo(KEY_APPNUMER, appMenuNodeId.toString()); if (appMenuInfo != null) { if (StringUtils.equalsIgnoreCase("kdec_totrdpagebyappmenu", appMenuInfo.getFormId())) { // 以新浏览器窗口打开第三方系统页面 //this.gotoApp(); } } } ``` ## 3.6 (单点登录第三方系统并)返回待打开页面的URL(OpenTrdPageUtils) ```language /** * 获取待打开的第三方页面地址 * @param isStaticPage 待打开的第三方页面是否为静态页面 * @return */ public static String getTrdSysTargetUrl(boolean isStaticPage) { String trdSysTargetUrl = null; if (isStaticPage) { // 跳转第三方静态页面, 亦可通过苍穹参数配置实现 trdSysTargetUrl = Parameter.TRDSYS_HOME_URL; } else { // 跳转第三方系统页面(带登录会话信息) DistributeSessionlessCache cache = CacheFactory.getCommonCacheFactory().getDistributeSessionlessCache("ssoLogin"); String accessToken = cache.get(RequestContext.get().getGlobalSessionId(), "kdcloudaccesstoken"); if (StringUtils.isEmpty(accessToken)) { logger.error("系统从金蝶云平台获取授权码(auth_code)时access_token为空!"); throw new KDBizException("请重新登录系统!"); } // 获取第三方系统的默认访问地址 trdSysTargetUrl = getTrdSysHomeUrl("kdec_tstapp2"); if (StringUtils.isEmpty(trdSysTargetUrl)) { logger.error("系统参数为空!"); throw new KDBizException("系统配置不完善, 请联系系统管理员操作!"); } // 单点登录成功之后打开第三方系统(另一套苍穹系统)门户首页 trdSysTargetUrl = String.format("%1$s%2$s", trdSysTargetUrl, "?formId=pc_main_console"); // 单点登录成功之后打开第三方系统(另一套苍穹系统)中【系统服务云】下应用【基础资料】的首页 // trdSysTargetUrl = String.format("%1$s%2$s", trdSysTargetUrl, "?formId=pc_main_console&appNumber=basedata"); // 单点登录成功之后打开第三方系统(另一套苍穹系统)中的指定页面(此处以币别列表界面为例) // trdSysTargetUrl = String.format("%1$s%2$s", trdSysTargetUrl, "index.html?billFormId=bd_currency&formId=bos_list"); if (StringUtils.isNotEmpty(accessToken)) { String authCode = SSOUtil.getAuthCode(accessToken); // 如果可从金蝶云平台获取到auth_code, 则系统自动单点登录到第三方系统页面; 否则需用户手动登录 if (StringUti

苍穹应用菜单触发 | 在新浏览器窗口打开第三方带会话信息页面

# 关键词:单点登录、页面集成、页面跳转、应用菜单点击、新浏览器窗口# 一、需求苍穹与第三方系统进行集成。用户登录苍穹之后,在应用首...
点击下载文档文档为doc格式

声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。

确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息
QQ群
  • 答案:my7c点击这里加入QQ群
支持邮箱
微信
  • 微信