yuanzhi_kuang 2 днів тому
батько
коміт
9c350a5e8d

+ 2 - 2
src/com/kingdee/eas/custom/integration/base/util/SHRApiUtils.java

@@ -113,9 +113,9 @@ public class SHRApiUtils {
         }
         IntegrationConfigService appConfigService = SpringContextHolder.getBean(IntegrationConfigService.class);
         CommonConfig commonConfig = appConfigService.getCommonConfig();
-        // ?????????????????????
+        // 已是移动 BOS 地址时,直接追加 mbos token
         if (redirectUrl.startsWith(commonConfig.getMobileBosUrl())) {
-            //????Mbos????
+            // 已指向 Mbos,补 token 即可
             return HttpUtils.appendUrlParam(redirectUrl, MbosTokenUtils.generateMbosTokenMap(userNumber));
         } else {
             logger.error("构建移动bos单点地址失败,重定向Mbos地址错误: {}", redirectUrl);

+ 18 - 18
src/com/kingdee/eas/custom/integration/weaver/controller/WeaverAuthController.java

@@ -33,9 +33,9 @@ import java.io.IOException;
 import java.net.URLEncoder;
 
 /**
- * ??? E10 OAuth ?????????????? base ?? AbstractAuthController ??锟斤拷????
- * ????????? /auth/weaver/app(.do)???????? UnifiedAuthController ?? platform ??????
- * Apusic ????? *.do??
+ * 泛微 E10 OAuth 入口,继承 base 的 AbstractAuthController。
+ * PC/待办深链请走 /auth/weaver/app(.do),不要依赖 UnifiedAuthController 的 platform UA 识别。
+ * Apusic 需同时映射 *.do。
  */
 @SkipAuth
 @SkipCallLog
@@ -63,11 +63,11 @@ public class WeaverAuthController extends AbstractAuthController {
     }
 
     /**
-     * ????/?????????????? appId ????? state ?????? OAuth??
-     * ???????锟斤拷 /auth/app?platform=weaver????????? base ?? UnifiedAuthController??
+     * 门户/待办显式入口:用 appId 生成 state 后跳转 OAuth。
+     * 不要用统一 /auth/app?platform=weaver(那条走 base 的 UnifiedAuthController)。
      */
     @GetMapping({"/weaver/app", "/weaver/app.do"})
-    @ApiDoc(name = "??????appId???", desc = "????????????????? state ????????")
+    @ApiDoc(name = "泛微显式appId入口", desc = "按 appId 生成 state 后进入 OAuth2 授权")
     public void app(@RequestParam String appId,
                     @RequestParam String redirect,
                     HttpServletResponse response) throws IOException {
@@ -86,7 +86,7 @@ public class WeaverAuthController extends AbstractAuthController {
     }
 
     @GetMapping({"/weaver", "/weaver.do"})
-    @ApiDoc(name = "?????????", desc = "???? state ????? OAuth2 ???")
+    @ApiDoc(name = "泛微授权入口", desc = "已有 state 时直接进入 OAuth2 授权")
     public void auth(@RequestParam(name = "state", required = false) String state,
                      HttpServletResponse response) throws IOException {
         if (StringUtils.isBlank(state)) {
@@ -96,7 +96,7 @@ public class WeaverAuthController extends AbstractAuthController {
     }
 
     @GetMapping({"/callback/weaver/pa", "/callback/weaver/pa.do"})
-    @ApiDoc(name = "???OAuth???(pa)", desc = "??? pa?????? .do")
+    @ApiDoc(name = "泛微OAuth回调(pa)", desc = "主应用 pa 回调,兼容 .do")
     public void callbackPa(@RequestParam(name = "code", required = false) String code,
                            @RequestParam(name = "state", required = false) String state,
                            HttpServletRequest request,
@@ -109,7 +109,7 @@ public class WeaverAuthController extends AbstractAuthController {
     }
 
     @GetMapping({"/callback/weaver/{appType}", "/callback/weaver/{appType}.do"})
-    @ApiDoc(name = "???OAuth???", desc = "??? appType?????? .do")
+    @ApiDoc(name = "泛微OAuth回调", desc = "按路径 appType 回调,兼容 .do")
     public void callback(@RequestParam(name = "code", required = false) String code,
                          @RequestParam(name = "state", required = false) String state,
                          @PathVariable String appType,
@@ -123,13 +123,13 @@ public class WeaverAuthController extends AbstractAuthController {
     }
 
     /**
-     * ????????????锟斤拷?????logout ?? service ?????锟斤拷?????? authorize??
-     * ????????? SHR ?????E10 ?????????????????????????????
-     * ?? appId+redirect ????????????? -> ???? -> ??? SHR??
-     * ???? service ??????????????????????????
+     * 联邦退出:把 logout 的 service 指回本系统 SSO 入口再进 authorize。
+     * 这样退出后再进 SHR 会先到 E10 登录页,而不是带着旧会话直接回 SHR。
+     * 传 appId+redirect 时拼出 SSO 入口;也可直接传 service。
+     * service 域名须在泛微退出重定向白名单内。
      */
     @GetMapping({"/weaver/logout", "/weaver/logout.do"})
-    @ApiDoc(name = "????????", desc = "????????????????????? SHR")
+    @ApiDoc(name = "泛微联邦退出", desc = "跳转泛微 logout,service 指向 SHR SSO 入口")
     public void logout(@RequestParam(name = "appId", required = false) String appId,
                        @RequestParam(name = "redirect", required = false) String redirect,
                        @RequestParam(name = "service", required = false) String service,
@@ -186,8 +186,8 @@ public class WeaverAuthController extends AbstractAuthController {
     }
 
     /**
-     * ???????????锟斤拷??????锟斤拷??????? sHR ?? POST ????????? Location ?? LTPA??
-     * pathAppType ???? state ? appType ??????
+     * 回调成功后:桌面进 sHR 用 POST 表单,避免 Location 带 LTPA。
+     * pathAppType 在 state 无 appType 时兜底。
      */
     private void doWeaverCallback(String code,
                                   String state,
@@ -241,8 +241,8 @@ public class WeaverAuthController extends AbstractAuthController {
         if ((device == DeviceType.MOBILE && isRedirectMbos)
                 || (device == DeviceType.DESKTOP && !isDesktopToShr)) {
             String mBosEid = config.getMBosEid();
-            if (StringUtils.isBlank(mBosEid) || mBosEid.contains("????锟斤拷")) {
-                throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "MBosEid 锟斤拷????");
+            if (StringUtils.isBlank(mBosEid) || mBosEid.contains("请填写")) {
+                throw new IntegrationException(CommonErrorCodes.PARAM_MISSING, "MBosEid 未配置");
             }
             redirect += "&eid=" + mBosEid;
             String finalRedirect = SHRApiUtils.generateToMBosUrl(userInfo.getNumber(), redirect);

+ 11 - 11
src/com/kingdee/eas/custom/integration/weaver/util/WeaverApiUtils.java

@@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
 /**
- * ??? E10 OAuth2 HTTP ???á?
+ * 泛微 E10 OAuth2 HTTP 工具。
  */
 public final class WeaverApiUtils {
 
@@ -46,18 +46,18 @@ public final class WeaverApiUtils {
                 .build()
                 .toUriString();
 
-        log.info("?????? access_token, client_id={}", appConfig.getAppId());
+        log.info("开始换取 access_token, client_id={}", appConfig.getAppId());
         ResponseEntity<Map> response = restTemplate.postForEntity(
                 url, new HttpEntity<>(buildJsonHeaders()), Map.class);
         Map<String, Object> body = response.getBody();
-        assertSuccess(body, WeaverErrorCodes.TOKEN_FAILED, "??? access_token");
+        assertSuccess(body, WeaverErrorCodes.TOKEN_FAILED, "换取 access_token");
 
         String accessToken = extractString(body, "access_token");
         if (StringUtils.isBlank(accessToken) && body.get("data") instanceof Map) {
             accessToken = extractString((Map<String, Object>) body.get("data"), "access_token");
         }
         if (StringUtils.isBlank(accessToken)) {
-            throw new WeaverIntegrationException(WeaverErrorCodes.TOKEN_FAILED, "access_token ???");
+            throw new WeaverIntegrationException(WeaverErrorCodes.TOKEN_FAILED, "access_token 为空");
         }
         return accessToken;
     }
@@ -71,11 +71,11 @@ public final class WeaverApiUtils {
                 .build()
                 .toUriString();
 
-        log.info("????????????");
+        log.info("开始获取用户信息");
         ResponseEntity<Map> response = restTemplate.postForEntity(
                 url, new HttpEntity<>(buildJsonHeaders()), Map.class);
         Map<String, Object> body = response.getBody();
-        assertSuccess(body, WeaverErrorCodes.PROFILE_FAILED, "?????????");
+        assertSuccess(body, WeaverErrorCodes.PROFILE_FAILED, "获取用户信息");
 
         String userId = extractUserId(body);
         if (StringUtils.isBlank(userId) && body.get("data") instanceof Map) {
@@ -84,7 +84,7 @@ public final class WeaverApiUtils {
         if (StringUtils.isBlank(userId)) {
             throw new WeaverIntegrationException(WeaverErrorCodes.USER_ID_EMPTY);
         }
-        log.info("?????????: {}", userId);
+        log.info("获取用户信息成功: {}", userId);
         return userId;
     }
 
@@ -92,7 +92,7 @@ public final class WeaverApiUtils {
         if (weaverConfig == null || !weaverConfig.isConfigured()) {
             throw new WeaverIntegrationException(WeaverErrorCodes.CONFIG_MISSING);
         }
-        // ???????Σ???? service ?? URLEncoder ?? build(true)
+        // service 交由 UriComponentsBuilder 编码,勿先 URLEncoder 再 build(true)
         return UriComponentsBuilder.fromHttpUrl(weaverConfig.getLogoutUrl())
                 .queryParam("service", serviceUrl)
                 .encode(StandardCharsets.UTF_8)
@@ -140,19 +140,19 @@ public final class WeaverApiUtils {
 
     private static void assertSuccess(Map<String, Object> body, ErrorCode errorCode, String action) {
         if (body == null) {
-            throw new WeaverIntegrationException(errorCode, action + "??????????");
+            throw new WeaverIntegrationException(errorCode, action + "响应体为空");
         }
         Object code = body.get("code");
         if (code != null && !"0".equals(String.valueOf(code))) {
             Object msg = body.get("msg");
             throw new WeaverIntegrationException(errorCode,
-                    action + "????" + (msg != null ? msg : body));
+                    action + "失败:" + (msg != null ? msg : body));
         }
         Object status = body.get("status");
         if (status != null && !"200".equals(String.valueOf(status))) {
             Object msg = body.get("msg");
             throw new WeaverIntegrationException(errorCode,
-                    action + "????" + (msg != null ? msg : body));
+                    action + "失败:" + (msg != null ? msg : body));
         }
     }
 }

+ 9 - 2
src/com/kingdee/eas/custom/integration/weaver/util/WeaverShrLanding.java

@@ -11,6 +11,8 @@ import org.springframework.web.util.HtmlUtils;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 
 /**
  * OAuth 成功后用 HTML 表单 POST 进 index2sso。
@@ -33,7 +35,12 @@ public final class WeaverShrLanding {
         try {
             String password = LtpaTokenManager.generate(userNumber, LtpaTokenManager.getDefaultLtpaConfig()).toString();
             String actionUrl = shrServerName.replaceAll("/+$", "") + "/shr/index2sso.jsp";
-            log.info("weaver SHR POST index2sso, username={}, action={}", userNumber, actionUrl);
+            // index2sso 会把 redirectTo 原样拼进 login.do 查询串且不再 encode;
+            // 表单先 encode 一次,getParameter 后仍保留 %26,避免 &inFrame 等被截断。
+            // 与产品 OTP2sso/OSF2sso 对 redirectTo 双重编码同一思路。
+            String redirectForForm = URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8.name());
+            log.info("weaver SHR POST index2sso, username={}, action={}, redirectRaw={}",
+                    userNumber, actionUrl, redirectUrl);
 
             try {
                 response.resetBuffer();
@@ -54,7 +61,7 @@ public final class WeaverShrLanding {
             out.write(HtmlUtils.htmlEscape(password));
             out.write("\"/>");
             out.write("<input type=\"hidden\" name=\"redirectTo\" value=\"");
-            out.write(HtmlUtils.htmlEscape(redirectUrl));
+            out.write(HtmlUtils.htmlEscape(redirectForForm));
             out.write("\"/></form>");
             out.write("<script type=\"text/javascript\">document.getElementById(\"ssoForm\").submit();</script>");
             out.write("</body></html>");

+ 10 - 10
src/com/kingdee/eas/custom/weaverTodo/config/WeaverTodoConfig.java

@@ -10,10 +10,10 @@ import java.nio.charset.StandardCharsets;
 import java.util.Properties;
 
 /**
- * ???????????????? EAS_HOME/server/properties/baoye/weaverTodoConfig.properties ?????
- * ????? SSO ?? oauth apps ??????????????? corpid/app_key??
- * ????? E10 ?????? OpenAPI ??????? /papi/openapi??
- * ????????? lastModified ?????????? properties ????????????
+ * 从 EAS_HOME/server/properties/baoye/weaverTodoConfig.properties 加载。
+ * 与 SSO 的 oauth apps 分开;此处放 OpenAPI 的 corpid/app_key 等。
+ * 走 E10 统一待办 OpenAPI(通常 /papi/openapi)。
+ * getInstance 按文件 lastModified 热加载,改 properties 后无需重启。
  */
 public class WeaverTodoConfig {
     private static final Logger logger = Logger.getLogger(WeaverTodoConfig.class);
@@ -27,7 +27,7 @@ public class WeaverTodoConfig {
     private static volatile String loadedPath;
 
     /**
-     * ??????????????????????????????????????????????
+     * 按配置文件路径与修改时间取实例;有变更则重新加载。
      */
     public static WeaverTodoConfig getInstance() {
         String path = System.getProperty("WEAVER_TODO_CONFIG_PATH", DEFAULT_PATH);
@@ -59,7 +59,7 @@ public class WeaverTodoConfig {
     private final String syscode;
     private final String shrServerName;
     private final String ssoAppId;
-    /** ???? pcurl ?? SSO ???????????? /qy/auth/weaver/app.do */
+    /** 待办 pcurl 的 SSO 入口,默认 /qy/auth/weaver/app.do */
     private final String ssoEntryPath;
     private final String approvePcPath;
     private final boolean enabled;
@@ -73,16 +73,16 @@ public class WeaverTodoConfig {
             try {
                 p.load(reader);
                 loaded = true;
-                logger.info("???? weaverTodoConfig: " + path + ", mtime=" + mtime);
+                logger.info("已加载 weaverTodoConfig: " + path + ", mtime=" + mtime);
             } finally {
                 reader.close();
             }
         } catch (Exception e) {
-            logger.error("???? weaverTodoConfig ???: " + path + "????????????", e);
+            logger.error("加载 weaverTodoConfig 失败: " + path + ",推送将关闭", e);
         }
         boolean wantEnable = loaded && !"false".equalsIgnoreCase(p.getProperty("weaver.todo.enabled", "true"));
         this.openapiHost = trimSlash(p.getProperty("weaver.openapi.host", ""));
-        // ???????????/papi/openapi/... ????????????????? /oauth2/authorize ??????? HTML
+        // 须使用 /papi/openapi/...;勿配成 /oauth2/authorize 一类门户页,否则会拿到 HTML
         this.authorizePath = normalizePath(p.getProperty("weaver.openapi.authorizePath",
                 "/papi/openapi/oauth2/authorize"));
         this.accessTokenPath = normalizePath(p.getProperty("weaver.openapi.accessTokenPath",
@@ -107,7 +107,7 @@ public class WeaverTodoConfig {
                 + " syscode=" + syscode
                 + " ssoEntryPath=" + ssoEntryPath);
         if (wantEnable && StringUtils.isAnyBlank(openapiHost, corpid, appKey, appSecret, syscode, shrServerName, ssoAppId)) {
-            logger.error("weaverTodoConfig ?????????????????????");
+            logger.error("weaverTodoConfig 必填项缺失,推送已关闭");
             this.enabled = false;
         } else {
             this.enabled = wantEnable;