浏览代码

腾讯企业邮箱登录优化

MaxKey 2 年之前
父节点
当前提交
c2d7230e2a

+ 3 - 0
NOTICE

@@ -14,6 +14,9 @@ It can be used directly without authorization. All copyrights, patents, trademar
 页脚中归属声明及版权声明不可忽略,否则视为侵权
 页脚中归属声明及版权声明不可忽略,否则视为侵权
 The attribution statement and copyright notice in the footer cannot be ignored, otherwise it will be deemed as infringement.
 The attribution statement and copyright notice in the footer cannot be ignored, otherwise it will be deemed as infringement.
 
 
+仅使用java程序情况,必须在软件前端页脚中添加此声明
+If only Java programs are used, this declaration must be added in the footer of the software front end
+
 Copyright  http://www.maxkey.top  All Rights Reserved.
 Copyright  http://www.maxkey.top  All Rights Reserved.
 
 
 License http://www.maxkey.top/zh/about/licenses.html
 License http://www.maxkey.top/zh/about/licenses.html

+ 6 - 1
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/ExtendApiAuthorizeEndpoint.java

@@ -57,10 +57,14 @@ public class ExtendApiAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 			@PathVariable("id") String id,
 			@PathVariable("id") String id,
 			@CurrentUser UserInfo currentUser){
 			@CurrentUser UserInfo currentUser){
 	    
 	    
-	    ModelAndView modelAndView=new ModelAndView("authorize/redirect_sso_submit");
+	    ModelAndView modelAndView = new ModelAndView("authorize/redirect_sso_submit");
+	    modelAndView.addObject("errorCode", 0);
+	    modelAndView.addObject("errorMessage", "");
+	    
 		Apps apps = getApp(id);
 		Apps apps = getApp(id);
 		_logger.debug(""+apps);
 		_logger.debug(""+apps);
 		if(ConstsBoolean.isTrue(apps.getIsAdapter())){
 		if(ConstsBoolean.isTrue(apps.getIsAdapter())){
+			_logger.debug("Adapter {}",apps.getAdapter());
 			AbstractAuthorizeAdapter adapter = (AbstractAuthorizeAdapter)Instance.newInstance(apps.getAdapter());
 			AbstractAuthorizeAdapter adapter = (AbstractAuthorizeAdapter)Instance.newInstance(apps.getAdapter());
 			Accounts account = getAccounts(apps,currentUser);
 			Accounts account = getAccounts(apps,currentUser);
 			if(apps.getCredential()==Apps.CREDENTIALS.USER_DEFINED && account == null) {
 			if(apps.getCredential()==Apps.CREDENTIALS.USER_DEFINED && account == null) {
@@ -73,6 +77,7 @@ public class ExtendApiAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 			
 			
 			return adapter.authorize(modelAndView);
 			return adapter.authorize(modelAndView);
 		}else{
 		}else{
+			_logger.debug("redirect_uri {}",apps.getLoginUrl());
 	        modelAndView.addObject("redirect_uri", apps.getLoginUrl());
 	        modelAndView.addObject("redirect_uri", apps.getLoginUrl());
 	        return modelAndView;
 	        return modelAndView;
 		}
 		}

+ 148 - 17
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiQQExmailAdapter.java

@@ -18,6 +18,8 @@
 package org.maxkey.authz.exapi.endpoint.adapter;
 package org.maxkey.authz.exapi.endpoint.adapter;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
 
 
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
 import org.maxkey.entity.Accounts;
 import org.maxkey.entity.Accounts;
@@ -29,6 +31,9 @@ import org.maxkey.web.HttpRequestAdapter;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.servlet.ModelAndView;
 import org.springframework.web.servlet.ModelAndView;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
 /**
 /**
  * https://exmail.qq.com/qy_mng_logic/doc
  * https://exmail.qq.com/qy_mng_logic/doc
  * exmail sso
  * exmail sso
@@ -42,6 +47,10 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 	//https://exmail.qq.com/qy_mng_logic/doc#10036
 	//https://exmail.qq.com/qy_mng_logic/doc#10036
 	static String AUTHKEY_URI 	= "https://api.exmail.qq.com/cgi-bin/service/get_login_url?access_token=%s&userid=%s";
 	static String AUTHKEY_URI 	= "https://api.exmail.qq.com/cgi-bin/service/get_login_url?access_token=%s&userid=%s";
 	
 	
+	final static  Cache<String, String> tokenCache = Caffeine.newBuilder()
+                										.expireAfterWrite(7200, TimeUnit.SECONDS)
+                										.build();
+	
 	Accounts account;
 	Accounts account;
 	
 	
 	@Override
 	@Override
@@ -59,31 +68,58 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 		if(details.getIsExtendAttr()==1){
 		if(details.getIsExtendAttr()==1){
 			extraAttrs=new ExtraAttrs(details.getExtendAttr());
 			extraAttrs=new ExtraAttrs(details.getExtendAttr());
 		}
 		}
-		_logger.debug("Extra Attrs "+extraAttrs);
-		String responseBody = new HttpRequestAdapter().get(
-				String.format(TOKEN_URI,details.getPrincipal(),details.getCredentials()),null);
-		Token token =JsonUtils.gson2Object(responseBody,Token.class);
-		_logger.debug("token {}" , token);
 		
 		
-		String authKeyBody = new HttpRequestAdapter().get(
-				String.format(AUTHKEY_URI,token.getAccess_token(),userInfo.getUsername()),null);
+		_logger.debug("Extra Attrs {}",extraAttrs);
 		
 		
-		LoginUrl loginUrl=JsonUtils.gson2Object(authKeyBody, LoginUrl.class);
-		_logger.debug("LoginUrl {} " , loginUrl);
+		String accessToken = getToken(details.getPrincipal(),details.getCredentials());
 		
 		
+		ExMailLoginUrl exMailLoginUrl = getLoginUrl(accessToken,userInfo.getUsername());
 		
 		
-        modelAndView.addObject("redirect_uri", loginUrl.getLogin_url());
+		if(exMailLoginUrl.errcode == 0) {
+			modelAndView.addObject("redirect_uri", exMailLoginUrl.getLogin_url());
+		}else {
+			_logger.error("Exception code {} , message {} , mapping message {} ,",
+					exMailLoginUrl.getErrcode(),
+					exMailLoginUrl.getErrmsg(),
+					exMailMsgMapper.get(exMailLoginUrl.getErrcode())
+					);
+			//remove accessToken 
+			tokenCache.invalidate(details.getPrincipal());
+			modelAndView.addObject("errorCode", exMailLoginUrl.getErrcode());
+			modelAndView.addObject("errorMessage", exMailMsgMapper.get(exMailLoginUrl.getErrcode()));
+		}
         
         
         return modelAndView;
         return modelAndView;
 	}
 	}
     
     
+    public String getToken(String corpid , String corpsecret) {
+    	String accessToken = tokenCache.getIfPresent(corpid);
+    	if(accessToken ==  null) {
+	    	String responseBody = new HttpRequestAdapter().get(String.format(TOKEN_URI,corpid,corpsecret),null);
+			Token token =JsonUtils.gson2Object(responseBody,Token.class);
+			_logger.debug("access_token {}" , token);
+			accessToken = token.getAccess_token();
+			tokenCache.put(corpid, accessToken);
+    	}
+    	return accessToken;
+    }
+    
+    public ExMailLoginUrl getLoginUrl(String accessToken,String userId) {
+    	_logger.debug("userId {}" , userId);
+		String authKeyBody = new HttpRequestAdapter().get(String.format(AUTHKEY_URI,accessToken,userId),null);
+		
+		ExMailLoginUrl exMailLoginUrl = JsonUtils.gson2Object(authKeyBody, ExMailLoginUrl.class);
+		_logger.debug("LoginUrl {} " , exMailLoginUrl);
+		return exMailLoginUrl;
+    }
+    
 	class ExMailMsg{
 	class ExMailMsg{
 		
 		
 		protected long expires_in;
 		protected long expires_in;
 		    
 		    
 		protected String errmsg;
 		protected String errmsg;
 		
 		
-		protected long errcode;
+		protected Integer errcode;
 
 
 		public ExMailMsg() {
 		public ExMailMsg() {
 		}
 		}
@@ -104,15 +140,13 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 			this.errmsg = errmsg;
 			this.errmsg = errmsg;
 		}
 		}
 
 
-		public long getErrcode() {
+		public Integer getErrcode() {
 			return errcode;
 			return errcode;
 		}
 		}
 
 
-		public void setErrcode(long errcode) {
+		public void setErrcode(Integer errcode) {
 			this.errcode = errcode;
 			this.errcode = errcode;
 		}
 		}
-		
-		
 	}
 	}
 	
 	
 	class Token extends ExMailMsg implements Serializable {
 	class Token extends ExMailMsg implements Serializable {
@@ -142,7 +176,7 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 
 
 	}
 	}
 	
 	
-	class LoginUrl extends ExMailMsg  implements Serializable {
+	class ExMailLoginUrl extends ExMailMsg  implements Serializable {
 		private static final long serialVersionUID = 3033047757268214198L;
 		private static final long serialVersionUID = 3033047757268214198L;
 		private String login_url;
 		private String login_url;
 		 
 		 
@@ -154,7 +188,7 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 			this.login_url = login_url;
 			this.login_url = login_url;
 		}
 		}
 		
 		
-		public LoginUrl() {
+		public ExMailLoginUrl() {
 		}
 		}
 
 
 		@Override
 		@Override
@@ -167,4 +201,101 @@ public class ExtendApiQQExmailAdapter extends AbstractAuthorizeAdapter {
 		}
 		}
 	}
 	}
 
 
+	public static HashMap<Integer,String> exMailMsgMapper = new HashMap<Integer,String>();
+	
+	static {
+		exMailMsgMapper.put(-1, "系统繁忙");
+		exMailMsgMapper.put(0, "请求成功");
+		exMailMsgMapper.put(40001, "获取access_token时CorpSecret错误,或者access_token无效");
+		exMailMsgMapper.put(40003, "不合法的UserID");
+		exMailMsgMapper.put(40013, "不合法的corpid");
+		exMailMsgMapper.put(40014, "不合法的access_token");
+		exMailMsgMapper.put(40057, "不合法的callbackurl或者callbackurl验证失败");
+		exMailMsgMapper.put(40091, "无效secert");
+		exMailMsgMapper.put(40092, "参数不合法");
+		exMailMsgMapper.put(40093, "请求并发过大,请降低并发并重试");
+		exMailMsgMapper.put(45009, "接口调用超过限制");
+		exMailMsgMapper.put(45024, "帐号数量超过上限");
+		exMailMsgMapper.put(50005, "企业已禁用");
+		exMailMsgMapper.put(60001, "部门长度不符合限制");
+		exMailMsgMapper.put(60002, "部门层级深度超过限制");
+		exMailMsgMapper.put(60003, "部门不存在");
+		exMailMsgMapper.put(60004, "父部门不存在");
+		exMailMsgMapper.put(60005, "不允许删除有成员的部门");
+		exMailMsgMapper.put(60006, "不允许删除有子部门的部门");
+		exMailMsgMapper.put(60007, "不允许删除根部门");
+		exMailMsgMapper.put(60008, "部门名称已存在");
+		exMailMsgMapper.put(60009, "部门名称含有非法字符");
+		exMailMsgMapper.put(60010, "部门存在循环关系");
+		exMailMsgMapper.put(60102, "UserID已存在");
+		exMailMsgMapper.put(60103, "手机号码不合法");
+		exMailMsgMapper.put(60104, "不合法的position参数");
+		exMailMsgMapper.put(60105, "部门ID数量超过上限");
+		exMailMsgMapper.put(60106, "不合法的userlist参数");
+		exMailMsgMapper.put(60111, "UserID不存在");
+		exMailMsgMapper.put(60112, "成员姓名不合法");
+		exMailMsgMapper.put(60114, "性别不合法");
+		exMailMsgMapper.put(60115, "激活码格式错误");
+		exMailMsgMapper.put(60116, "邮箱回收站内已存在相同的帐号");
+		exMailMsgMapper.put(60118, "userid在企业微信重复");
+		exMailMsgMapper.put(60119, "用户未绑定(删除、回收站状态)");
+		exMailMsgMapper.put(60120, "密码和手机号不能同时为空");
+		exMailMsgMapper.put(60123, "无效的部门id");
+		exMailMsgMapper.put(60124, "无效的父部门id");
+		exMailMsgMapper.put(60125, "非法部门名字,长度超过限制、重名等,重名包括与csv文件中同级部门重名或者与旧组织架构包含成员的同级部门重名");
+		exMailMsgMapper.put(60126, "创建部门失败");
+		exMailMsgMapper.put(60127, "缺少部门id");
+		exMailMsgMapper.put(60128, "帐号已绑定手机或微信,需员工修改密码");
+		exMailMsgMapper.put(60201, "不合法的标签id");
+		exMailMsgMapper.put(60202, "缺少标签id");
+		exMailMsgMapper.put(60203, "不合法的标签名");
+		exMailMsgMapper.put(60204, "标签名已存在");
+		exMailMsgMapper.put(60205, "所有参数都非法");
+		exMailMsgMapper.put(60301, "不合法的type参数");
+		exMailMsgMapper.put(60302, "不合法的option参数");
+		exMailMsgMapper.put(600001, "Userid与别名冲突");
+		exMailMsgMapper.put(600002, "Userid与Groupid冲突");
+		exMailMsgMapper.put(600003, "无效密码或者是弱密码");
+		exMailMsgMapper.put(600004, "别名无效");
+		exMailMsgMapper.put(600005, "别名与userid或者Groupid冲突");
+		exMailMsgMapper.put(600006, "别名数量达到上限");
+		exMailMsgMapper.put(600007, "Groupid无效");
+		exMailMsgMapper.put(600008, "邮件群组不存在");
+		exMailMsgMapper.put(600009, "群组成员为空");
+		exMailMsgMapper.put(600010, "Userlist无效,可能是个别成员无效");
+		exMailMsgMapper.put(600011, "Grouplist无效,可能是个别成员无效");
+		exMailMsgMapper.put(600012, "Partylist无效,可能是个别成员无效");
+		exMailMsgMapper.put(600013, "群发权限类型无效");
+		exMailMsgMapper.put(600014, "群发权限成员无效");
+		exMailMsgMapper.put(600015, "邮件群组已存在");
+		exMailMsgMapper.put(600016, "Userlist部分成员未找到");
+		exMailMsgMapper.put(600017, "Partylist部分成员未找到");
+		exMailMsgMapper.put(600018, "Grouplist部分成员未找到");
+		exMailMsgMapper.put(600019, "邮件群组名称含有非法字符");
+		exMailMsgMapper.put(600020, "邮件群组存在循环");
+		exMailMsgMapper.put(600021, "邮件群组嵌套超过层数");
+		exMailMsgMapper.put(600023, "群发权限成员缺失");
+		exMailMsgMapper.put(600024, "Groupid与userid或者别名冲突");
+		exMailMsgMapper.put(600025, "座机号码无效");
+		exMailMsgMapper.put(600026, "编号无效");
+		exMailMsgMapper.put(600027, "批量检查的成员数超过限额");
+		exMailMsgMapper.put(600034, "不合法的fuzzy参数");
+		exMailMsgMapper.put(600035, "不合法的业务邮箱账号");
+		exMailMsgMapper.put(600036, "密码不允许修改");
+		exMailMsgMapper.put(600037, "不合法的业务邮箱ID");
+		exMailMsgMapper.put(600038, "不合法的业务邮箱名称");
+		exMailMsgMapper.put(600039, "业务邮箱账号已存在");
+		exMailMsgMapper.put(600040, "业务邮箱名称已存在");
+		exMailMsgMapper.put(600041, "业务邮箱ID不存在");
+		exMailMsgMapper.put(601001, "日志查询的时间无效");
+		exMailMsgMapper.put(601002, "日志查询的时间超过限制");
+		exMailMsgMapper.put(601003, "日志查询的域名无效");
+		exMailMsgMapper.put(601004, "日志查询的域名不存在");
+		exMailMsgMapper.put(601005, "不合法的mailtype参数");
+		exMailMsgMapper.put(601006, "不合法的type参数");
+		exMailMsgMapper.put(602005, "应用没有访问此API的权限");
+		exMailMsgMapper.put(604001, "基础版企业无权限操作专业版功能");
+		exMailMsgMapper.put(604002, "企业VIP人员达到上限");
+		exMailMsgMapper.put(604003, "不合法的setvip参数");
+	}
 }
 }

+ 8 - 3
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/authorize/redirect_sso_submit.ftl

@@ -5,18 +5,23 @@
     <#include  "authorize_common.ftl">
     <#include  "authorize_common.ftl">
     <script type="text/javascript">
     <script type="text/javascript">
         function redirectToLogin(){
         function redirectToLogin(){
-            window.top.location.href ="${redirect_uri!}";
+           <#if redirect_uri??>
+                window.top.location.href ="${redirect_uri!}";
+           </#if>
        }
        }
     </script>
     </script>
 </head>
 </head>
 
 
-<body onload="redirectToLogin()"  style="display:none">
-<form id="redirect_sso_form" name="redirect_sso_form" action="${redirect_uri!}" method="get">
+<body onload="redirectToLogin()"  >
+    <form id="redirect_sso_form" name="redirect_sso_form" action="${redirect_uri!}" method="get" style="display:none">
         <table style="width:100%">
         <table style="width:100%">
             <tr>
             <tr>
                 <td colspan="2"><input type="submit"  name="submitBtn" value="Continue..." /></td>
                 <td colspan="2"><input type="submit"  name="submitBtn" value="Continue..." /></td>
             </tr>
             </tr>
         </table>
         </table>
     </form>
     </form>
+    <#if errorMessage??>
+        ${errorMessage!}
+    </#if>
 </body>
 </body>
 </html>
 </html>