Browse Source

2. 根据钉钉userid获取用户信息接口
后端需将前端钉钉回调地址做成配置项,且回调前端地址是添加 ?ticket=xxx

vincent 3 years ago
parent
commit
69db20dd11

+ 195 - 1
maxkey-authentications/maxkey-authentication-social/src/main/java/org/maxkey/authn/support/socialsignon/SocialSignOnEndpoint.java

@@ -22,13 +22,37 @@ package org.maxkey.authn.support.socialsignon;
 
 import javax.servlet.http.HttpServletRequest;
 
+import com.alibaba.fastjson.JSON;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiGettokenRequest;
+import com.dingtalk.api.request.OapiUserGetbyunionidRequest;
+import com.dingtalk.api.request.OapiV2UserGetRequest;
+import com.dingtalk.api.response.OapiGettokenResponse;
+import com.dingtalk.api.response.OapiUserGetbyunionidResponse;
+import com.dingtalk.api.response.OapiV2UserGetResponse;
+import com.dingtalk.api.response.OapiV2UserListResponse;
+import com.taobao.api.ApiException;
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.maxkey.authn.AbstractAuthenticationProvider;
 import org.maxkey.authn.LoginCredential;
+import org.maxkey.authn.support.jwt.JwtLoginService;
 import org.maxkey.authn.support.socialsignon.service.SocialsAssociate;
 import org.maxkey.constants.ConstantsLoginType;
+import org.maxkey.constants.ConstantsPasswordSetType;
 import org.maxkey.entity.SocialsProvider;
+import org.maxkey.entity.UserInfo;
+import org.maxkey.persistence.redis.RedisConnection;
+import org.maxkey.persistence.redis.RedisConnectionFactory;
+import org.maxkey.persistence.service.UserInfoService;
+import org.maxkey.util.StringUtils;
 import org.maxkey.web.WebContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.web.WebAttributes;
 import org.springframework.stereotype.Controller;
@@ -40,6 +64,8 @@ import org.springframework.web.servlet.ModelAndView;
 
 import me.zhyd.oauth.request.AuthRequest;
 
+import java.util.Random;
+
 /**
  * @author Crystal.Sea
  *
@@ -48,6 +74,26 @@ import me.zhyd.oauth.request.AuthRequest;
 @RequestMapping(value = "/logon/oauth20")
 public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint
 {
+    @Value("${maxkey.callback.url}")
+    private String callbackUrl;
+
+    @Autowired
+    @Qualifier("authenticationProvider")
+    AbstractAuthenticationProvider authenticationProvider;
+
+    @Autowired
+    @Qualifier("jwtLoginService")
+    JwtLoginService jwtLoginService;
+
+    @Autowired
+    @Qualifier("userInfoService")
+    private UserInfoService userInfoService;
+
+
+    @Autowired
+    RedisConnectionFactory redisConnectionFactory;
+
+
     final static Logger _logger = LoggerFactory.getLogger(SocialSignOnEndpoint.class);
 
     public ModelAndView socialSignOnAuthorize(HttpServletRequest request, String provider)
@@ -141,6 +187,24 @@ public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint
         return scanQRCodeProvider;
     }
 
+    /**
+     * 获取accessToken
+     *
+     * @return
+     * @throws ApiException
+     */
+    public String getAccessToken() throws ApiException
+    {
+        SocialsProvider socialSignOnProvider = socialSignOnProviderService.get(provider);
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
+        OapiGettokenRequest request = new OapiGettokenRequest();
+        request.setAppkey(socialSignOnProvider.getClientId());
+        request.setAppsecret(socialSignOnProvider.getClientSecret());
+        request.setHttpMethod("GET");
+        OapiGettokenResponse response = client.execute(request);
+        return response.getAccessToken();
+    }
+
 
 //	@RequestMapping(value={"/callback/{provider}"}, method = RequestMethod.GET)
 //	public ModelAndView callback(@PathVariable String provider) {
@@ -188,6 +252,29 @@ public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint
     @RequestMapping(value = {"/callback/{provider}"}, method = RequestMethod.GET)
     public ModelAndView callbackDingTalk(@PathVariable String provider)
     {
+        // 对 callbackUrl 进行处理
+        if (StringUtils.isNotEmpty(callbackUrl))
+        {
+            if (callbackUrl.contains("?") || callbackUrl.contains("&"))
+            {
+                callbackUrl += "&ticket=";
+            } else
+            {
+                callbackUrl += "?ticket=";
+            }
+        }
+        // 获取access_token,注意正式代码要有异常流处理
+        //
+        String access_token = "";
+
+        try
+        {
+            access_token = getAccessToken();
+            _logger.debug("access_token :{}" + access_token);
+        } catch (Exception e)
+        {
+
+        }
         //auth call back may exception
         // TODO  钉钉 回调函数
         try
@@ -211,7 +298,53 @@ public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint
                     || socialSignOnType.equals(""))
             {
                 socialSignOn(socialsAssociate);
-                return WebContext.redirect("http://www.baidu.com");
+                // 先判断用户是否存在
+                // 1. 不存在 先存入用户
+                // 根据unionid获取userid
+                DingTalkClient clientDingTalkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
+                OapiUserGetbyunionidRequest reqGetbyunionidRequest = new OapiUserGetbyunionidRequest();
+                reqGetbyunionidRequest.setUnionid(accountId);
+                OapiUserGetbyunionidResponse oapiUserGetbyunionidResponse = clientDingTalkClient.execute(reqGetbyunionidRequest, getAccessToken());
+                _logger.debug("accessToken >>>" + getAccessToken());
+                // 根据userId获取用户信息
+                String userid = oapiUserGetbyunionidResponse.getResult().getUserid();
+                _logger.debug("userid >>>" + userid);
+                DingTalkClient clientDingTalkClient2 = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
+                OapiV2UserGetRequest reqGetRequest = new OapiV2UserGetRequest();
+                reqGetRequest.setUserid(userid);
+                reqGetRequest.setLanguage("zh_CN");
+                OapiV2UserGetResponse rspGetResponse = clientDingTalkClient2.execute(reqGetRequest, getAccessToken());
+                OapiV2UserGetResponse.UserGetResponse userGetResponse = rspGetResponse.getResult();
+
+                UserInfo userInfo = userInfoService.getMapper().queryUserInfoByAssociateId(userid);
+                if (null == userInfo)
+                {
+                    userInfo = buildUserInfo(userGetResponse);
+                    userInfoService.merge(userInfo);
+                }
+
+                // 2. 存在 直接登录拼接ticket
+                String token = jwtLoginService.buildLoginJwt();
+                RedisConnection redisConnection = redisConnectionFactory.getConnection();
+                // 默认 7天
+                // 先获取之前有没有token
+                String oldToken = redisConnection.get(userInfo.getId());
+                if (com.alibaba.cloud.commons.lang.StringUtils.isNotEmpty(oldToken))
+                {
+                    redisConnection.delete(userInfo.getId());
+                    redisConnection.delete(oldToken);
+                }
+                redisConnection.setex(userInfo.getId(), 60 * 60 * 24 * 7, token);
+                redisConnection.setex(token, 60 * 60 * 24 * 7, JSON.toJSONString(userInfo));
+                String ticket = createRandomCharData(36);
+
+                redisConnection.setex(ticket, 60 * 60 * 24 * 1, JSON.toJSONString(userInfo));
+                redisConnection.close();
+                _logger.debug("token >>>" + token);
+
+
+                // TODO  整合前端的地址
+                return WebContext.redirect(callbackUrl + ticket);
             } else
             {
                 socialBind(socialsAssociate);
@@ -234,6 +367,67 @@ public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint
         return WebContext.redirect("/login");
     }
 
+    public String createRandomCharData(int length)
+    {
+        StringBuilder sb = new StringBuilder("TT-");
+        Random rand = new Random();//随机用以下三个随机生成器
+        Random randdata = new Random();
+        int data = 0;
+        for (int i = 0; i < length; i++)
+        {
+            int index = rand.nextInt(3);
+            //目的是随机选择生成数字,大小写字母
+            switch (index)
+            {
+                case 0:
+                    data = randdata.nextInt(10);//仅仅会生成0~9
+                    sb.append(data);
+                    break;
+                case 1:
+                    data = randdata.nextInt(26) + 65;//保证只会产生65~90之间的整数
+                    sb.append((char) data);
+                    break;
+                case 2:
+                    data = randdata.nextInt(26) + 97;//保证只会产生97~122之间的整数
+                    sb.append((char) data);
+                    break;
+            }
+        }
+        String result = sb.toString();
+        _logger.info("生成的随机数兑换码为{}", result);
+        return result;
+    }
+
+
+    public UserInfo buildUserInfo(OapiV2UserGetResponse.UserGetResponse user)
+    {
+        UserInfo userInfo = new UserInfo();
+        // 手机号 作为用户名
+        userInfo.setUsername(user.getMobile());//鐧诲綍鍚�
+        userInfo.setNickName(user.getName());//鐢ㄦ埛鍚�
+        userInfo.setDisplayName(user.getName());//鐢ㄦ埛鍚�
+        userInfo.setFormattedName(user.getName());//鐢ㄦ埛鍚�
+        userInfo.setAssociateId(user.getUserid()); // 第三方用户的id
+
+        userInfo.setEmail(user.getEmail());
+        userInfo.setEntryDate(new DateTime(user.getHiredDate()).toString(DateTimeFormat.forPattern("yyyy-MM-dd")));
+        userInfo.setMobile(user.getMobile());//鎵嬫満
+        userInfo.setDepartmentId(user.getDeptIdList().get(0) + "");
+        userInfo.setJobTitle(user.getTitle());//鑱屽姟
+        userInfo.setWorkEmail(user.getOrgEmail());//宸ヤ綔閭欢
+        userInfo.setWorkPhoneNumber(user.getTelephone());//鍏徃鐢佃瘽
+        userInfo.setWorkOfficeName(user.getWorkPlace());//鍔炲叕瀹�
+        userInfo.setDescription(user.getRemark());//澶囨敞
+
+        userInfo.setPassword("123456");
+        userInfo.setPasswordSetType(ConstantsPasswordSetType.PASSWORD_NORMAL);
+        userInfo.setStatus(1);
+//        userInfo.setDepartmentId(user.getd);
+//        userInfo.setDepartment(dept.getName());
+
+        return userInfo;
+    }
+
     public boolean socialBind(SocialsAssociate socialsAssociate)
     {
         if (null == socialsAssociate)

+ 180 - 131
maxkey-authentications/maxkey-authentication-social/src/main/java/org/maxkey/authn/support/socialsignon/service/SocialSignOnProviderService.java

@@ -1,19 +1,19 @@
 /*
  * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 
 package org.maxkey.authn.support.socialsignon.service;
 
@@ -35,160 +35,209 @@ import me.zhyd.oauth.model.AuthResponse;
 import me.zhyd.oauth.model.AuthUser;
 import me.zhyd.oauth.request.*;
 
-public class SocialSignOnProviderService{
-	private static Logger _logger = LoggerFactory.getLogger(SocialSignOnProviderService.class);
-	
-	   private static final String DEFAULT_SELECT_STATEMENT = "select * from mxk_socials_provider where status = 1  order by sortindex";
-	    
-	   
-	List<SocialsProvider> socialSignOnProviders = new ArrayList<SocialsProvider>();
-	
-	HashMap<String ,SocialsProvider>socialSignOnProviderMaps=new HashMap<String ,SocialsProvider>();
-	
-	private final JdbcTemplate jdbcTemplate;
-	
-	public SocialSignOnProviderService(JdbcTemplate jdbcTemplate) {
-        this.jdbcTemplate=jdbcTemplate; 
+public class SocialSignOnProviderService
+{
+    private static Logger _logger = LoggerFactory.getLogger(SocialSignOnProviderService.class);
+
+    private static final String DEFAULT_SELECT_STATEMENT = "select * from mxk_socials_provider where status = 1  order by sortindex";
+
+
+    List<SocialsProvider> socialSignOnProviders = new ArrayList<SocialsProvider>();
+
+    HashMap<String, SocialsProvider> socialSignOnProviderMaps = new HashMap<String, SocialsProvider>();
+
+    private final JdbcTemplate jdbcTemplate;
+
+    public SocialSignOnProviderService(JdbcTemplate jdbcTemplate)
+    {
+        this.jdbcTemplate = jdbcTemplate;
     }
 
-	
-	public SocialsProvider get(String provider){
-		return socialSignOnProviderMaps.get(provider);
-	}
-	
-	public AuthRequest  getAuthRequest(String provider,ApplicationConfig applicationConfig)  throws Exception {
-		AuthRequest authRequest = null;
-		AuthConfig authConfig = AuthConfig.builder()
-				.clientId(this.get(provider).getClientId())
-				.clientSecret(this.get(provider).getClientSecret())
-				.redirectUri(applicationConfig.getServerPrefix()+ "/logon/oauth20/callback/"+provider)
-				.build();
-		
-		if(provider.equalsIgnoreCase("WeChatOpen")) {
-			authRequest = new AuthWeChatOpenRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("sinaweibo")) {
-			authRequest = new AuthWeiboRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("qq")) {
-			authRequest = new AuthQqRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("Alipay")) {
-		    String alipayPublicKey = "";
-			authRequest = new AuthAlipayRequest(authConfig,alipayPublicKey);
-		}else if(provider.equalsIgnoreCase("Twitter")) {
-			authRequest = new AuthTwitterRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("google")) {
-			authRequest = new AuthGoogleRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("microsoft")) {
-			authRequest = new AuthMicrosoftRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("Linkedin")) {
-			authRequest = new AuthLinkedinRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("DingTalk")) {
-			authRequest = new AuthDingTalkRequest(authConfig);
-		}else if(provider.equalsIgnoreCase("gitee")) {
+
+    public SocialsProvider get(String provider)
+    {
+        return socialSignOnProviderMaps.get(provider);
+    }
+
+    public AuthRequest getAuthRequest(String provider, ApplicationConfig applicationConfig) throws Exception
+    {
+        AuthRequest authRequest = null;
+        AuthConfig authConfig = AuthConfig.builder()
+                .clientId(this.get(provider).getClientId())
+                .clientSecret(this.get(provider).getClientSecret())
+                .redirectUri(applicationConfig.getServerPrefix() + "/logon/oauth20/callback/" + provider)
+                .build();
+
+        if (provider.equalsIgnoreCase("WeChatOpen"))
+        {
+            authRequest = new AuthWeChatOpenRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("sinaweibo"))
+        {
+            authRequest = new AuthWeiboRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("qq"))
+        {
+            authRequest = new AuthQqRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("Alipay"))
+        {
+            String alipayPublicKey = "";
+            authRequest = new AuthAlipayRequest(authConfig, alipayPublicKey);
+        } else if (provider.equalsIgnoreCase("Twitter"))
+        {
+            authRequest = new AuthTwitterRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("google"))
+        {
+            authRequest = new AuthGoogleRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("microsoft"))
+        {
+            authRequest = new AuthMicrosoftRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("Linkedin"))
+        {
+            authRequest = new AuthLinkedinRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("DingTalk"))
+        {
+            authRequest = new AuthDingTalkRequest(authConfig);
+        } else if (provider.equalsIgnoreCase("gitee"))
+        {
             authRequest = new AuthGiteeRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Baidu")) {
+        } else if (provider.equalsIgnoreCase("Baidu"))
+        {
             authRequest = new AuthBaiduRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Douyin")) {
+        } else if (provider.equalsIgnoreCase("Douyin"))
+        {
             authRequest = new AuthDouyinRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Eleme")) {
+        } else if (provider.equalsIgnoreCase("Eleme"))
+        {
             authRequest = new AuthElemeRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Feishu")) {
+        } else if (provider.equalsIgnoreCase("Feishu"))
+        {
             authRequest = new AuthFeishuRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Github")) {
+        } else if (provider.equalsIgnoreCase("Github"))
+        {
             authRequest = new AuthGithubRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Gitlab")) {
+        } else if (provider.equalsIgnoreCase("Gitlab"))
+        {
             authRequest = new AuthGitlabRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Huawei")) {
+        } else if (provider.equalsIgnoreCase("Huawei"))
+        {
             authRequest = new AuthHuaweiRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("jd")) {
+        } else if (provider.equalsIgnoreCase("jd"))
+        {
             authRequest = new AuthJdRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Meituan")) {
+        } else if (provider.equalsIgnoreCase("Meituan"))
+        {
             authRequest = new AuthMeituanRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Mi")) {
+        } else if (provider.equalsIgnoreCase("Mi"))
+        {
             authRequest = new AuthMiRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Oschina")) {
+        } else if (provider.equalsIgnoreCase("Oschina"))
+        {
             authRequest = new AuthOschinaRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Taobao")) {
+        } else if (provider.equalsIgnoreCase("Taobao"))
+        {
             authRequest = new AuthTaobaoRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("Toutiao")) {
+        } else if (provider.equalsIgnoreCase("Toutiao"))
+        {
             authRequest = new AuthToutiaoRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("WeChatQyQrcode")) {
+        } else if (provider.equalsIgnoreCase("WeChatQyQrcode"))
+        {
             authRequest = new AuthWeChatEnterpriseQrcodeRequest(authConfig);
-        }else if(provider.equalsIgnoreCase("workweixin")) {
+        } else if (provider.equalsIgnoreCase("workweixin"))
+        {
             authRequest = new AuthWeChatEnterpriseWebRequest(authConfig);
         }
-		
-		return authRequest;
-	}
-	
-	public String getAccountId(String provider,AuthResponse<?> authResponse)  throws Exception {
-	    if(authResponse.getData() != null) {
-	        AuthUser authUser = (AuthUser)authResponse.getData();
-	        _logger.debug("AuthUser[{},{},{},{},{},{},{},{},{},{},{},{}]",
-	                authUser.getUuid(),
-	                authUser.getUsername(),
-	                authUser.getNickname(),
-	                authUser.getGender(),
-	                authUser.getEmail(),
-	                authUser.getCompany(),
-	                authUser.getBlog(),
-	                authUser.getLocation(),
-	                authUser.getRemark(),
-	                authUser.getSource(),
-	                authUser.getBlog(),
-	                authUser.getAvatar());
-	        _logger.debug("RawUserInfo {}",authUser.getRawUserInfo());
-    		if(provider.equalsIgnoreCase("WeChatOpen")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("sinaweibo")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("qq")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("Alipay")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("Twitter")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("google")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("microsoft")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("Linkedin")) {
-    			return authUser.getUuid();
-    		}else if(provider.equalsIgnoreCase("DingTalk")) {
-    			return authUser.getUuid();
-    		}else {
-    		    return authUser.getUuid();
-    		}
-	    }
-	    return null;
-	}
-	public List<SocialsProvider> getSocialSignOnProviders() {
-		return socialSignOnProviders;
-	}
-	
-	public void loadSocialsProviders() {
-	    List<SocialsProvider> listSocialsProvider=jdbcTemplate.query(
-	            DEFAULT_SELECT_STATEMENT,
+
+        return authRequest;
+    }
+
+    public String getAccountId(String provider, AuthResponse<?> authResponse) throws Exception
+    {
+        if (authResponse.getData() != null)
+        {
+            AuthUser authUser = (AuthUser) authResponse.getData();
+            _logger.info("*******" + authUser);
+            _logger.debug("AuthUser[{},{},{},{},{},{},{},{},{},{},{},{}]",
+                    authUser.getUuid(),
+                    authUser.getUsername(),
+                    authUser.getNickname(),
+                    authUser.getGender(),
+                    authUser.getEmail(),
+                    authUser.getCompany(),
+                    authUser.getBlog(),
+                    authUser.getLocation(),
+                    authUser.getRemark(),
+                    authUser.getSource(),
+                    authUser.getBlog(),
+                    authUser.getAvatar());
+            _logger.debug("RawUserInfo {}", authUser.getRawUserInfo());
+            if (provider.equalsIgnoreCase("WeChatOpen"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("sinaweibo"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("qq"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("Alipay"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("Twitter"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("google"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("microsoft"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("Linkedin"))
+            {
+                return authUser.getUuid();
+            } else if (provider.equalsIgnoreCase("DingTalk"))
+            {
+                return authUser.getUuid();
+            } else
+            {
+                return authUser.getUuid();
+            }
+        }
+        return null;
+    }
+
+    public List<SocialsProvider> getSocialSignOnProviders()
+    {
+        return socialSignOnProviders;
+    }
+
+    public void loadSocialsProviders()
+    {
+        List<SocialsProvider> listSocialsProvider = jdbcTemplate.query(
+                DEFAULT_SELECT_STATEMENT,
                 new SocialsProviderRowMapper());
         _logger.trace("query SocialsProvider " + listSocialsProvider);
-        
-        for(SocialsProvider socialsProvider : listSocialsProvider){
+
+        for (SocialsProvider socialsProvider : listSocialsProvider)
+        {
             socialSignOnProviderMaps.put(socialsProvider.getProvider(), socialsProvider);
-            _logger.debug("Social Provider " + socialsProvider.getProvider() 
-                                             + "(" + socialsProvider.getProviderName()+")");
-            if(!socialsProvider.getHidden().equals("true")) {
+            _logger.debug("Social Provider " + socialsProvider.getProvider()
+                    + "(" + socialsProvider.getProviderName() + ")");
+            if (!socialsProvider.getHidden().equals("true"))
+            {
                 this.socialSignOnProviders.add(socialsProvider);
             }
         }
-    
-    _logger.debug("social SignOn Providers {}" , this.socialSignOnProviders);
-	}
-	
-	
-	private final class SocialsProviderRowMapper  implements RowMapper<SocialsProvider> {
+
+        _logger.debug("social SignOn Providers {}", this.socialSignOnProviders);
+    }
+
+
+    private final class SocialsProviderRowMapper implements RowMapper<SocialsProvider>
+    {
         @Override
         public SocialsProvider mapRow(ResultSet rs, int rowNum)
-                throws SQLException {
-            SocialsProvider socialsProvider=new SocialsProvider();
+                throws SQLException
+        {
+            SocialsProvider socialsProvider = new SocialsProvider();
             socialsProvider.setId(rs.getString("id"));
             socialsProvider.setProvider(rs.getString("provider"));
             socialsProvider.setProviderName(rs.getString("providername"));

+ 18 - 0
maxkey-core/src/main/java/org/maxkey/entity/UserInfo.java

@@ -257,9 +257,14 @@ public class UserInfo extends JpaBaseEntity {
     String modifiedDate;
     @Column
     int status;
+
     @Column
     String description;
 
+
+    @Column
+    String associateId; // 第三方同步过来用户id,如钉钉userid等
+
     List<Organizations> depts;
     
     List<UserInfoAdjoint> adjoints;
@@ -1260,6 +1265,17 @@ public class UserInfo extends JpaBaseEntity {
         this.adjoints = adjoints;
     }
 
+    public String getAssociateId()
+    {
+        return associateId;
+    }
+
+    public void setAssociateId(String associateId)
+    {
+        this.associateId = associateId;
+    }
+
+
     @Override
 	public String toString() {
 		StringBuilder builder = new StringBuilder();
@@ -1461,6 +1477,8 @@ public class UserInfo extends JpaBaseEntity {
 		builder.append(status);
 		builder.append(", description=");
 		builder.append(description);
+        builder.append(", associateId=");
+        builder.append(associateId);
 		builder.append("]");
 		return builder.toString();
 	}

+ 2 - 1
maxkey-identitys/maxkey-synchronizers-dingding/src/main/java/org/maxkey/synchronizer/dingding/DingdingUsersService.java

@@ -103,7 +103,7 @@ public class DingdingUsersService implements ISynchronizerService
                             //绑定用户
                             SocialsAssociate socialsAssociate = new SocialsAssociate();
                             socialsAssociate.setProvider("dingtalk");
-                            socialsAssociate.setSocialUserId(user.getUnionid());
+                            socialsAssociate.setSocialUserId(user.getUserid());
                             socialsAssociate.setUserId(userInfo.getId());
                             socialsAssociate.setUsername(userInfo.getUsername());
                             socialsAssociateService.merge(socialsAssociate);
@@ -137,6 +137,7 @@ public class DingdingUsersService implements ISynchronizerService
         userInfo.setNickName(user.getName());//鐢ㄦ埛鍚�
         userInfo.setDisplayName(user.getName());//鐢ㄦ埛鍚�
         userInfo.setFormattedName(user.getName());//鐢ㄦ埛鍚�
+        userInfo.setAssociateId(user.getUserid()); // 第三方用户的id
 
         userInfo.setEmail(user.getEmail());
         userInfo.setEntryDate(new DateTime(user.getHiredDate()).toString(DateTimeFormat.forPattern("yyyy-MM-dd")));

+ 3 - 0
maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/UserInfoMapper.java

@@ -74,4 +74,7 @@ public interface UserInfoMapper  extends IJpaBaseMapper<UserInfo>{
     
     @Update("update mxk_userinfo set gridlist =  #{gridList} where id = #{id}")
 	public int updateGridList(UserInfo userInfo) ;
+
+	@Select("select * from  mxk_userinfo where   ASSOCIATEID = #{associateId}")
+	public UserInfo queryUserInfoByAssociateId(String associateId);
 }

+ 1 - 0
maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java

@@ -90,6 +90,7 @@ public class UserInfoService extends JpaBaseService<UserInfo>
         return (UserInfoMapper) super.getMapper();
     }
 
+
     public boolean insert(UserInfo userInfo)
     {
         userInfo = passwordEncoder(userInfo);

+ 64 - 6
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/ThirdLoginController.java

@@ -3,12 +3,18 @@ package org.maxkey.web.contorller;
 import com.alibaba.cloud.commons.lang.StringUtils;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiGettokenRequest;
+import com.dingtalk.api.response.OapiGettokenResponse;
 import com.nimbusds.jwt.SignedJWT;
+import com.taobao.api.ApiException;
 import io.swagger.annotations.ApiOperation;
 import org.maxkey.authn.AbstractAuthenticationProvider;
 import org.maxkey.authn.realm.jdbc.JdbcAuthenticationRealm;
 import org.maxkey.authn.support.jwt.JwtLoginService;
 import org.maxkey.authn.support.socialsignon.service.SocialSignOnProviderService;
+import org.maxkey.authn.support.socialsignon.service.SocialsAssociateService;
 import org.maxkey.authz.cas.endpoint.ticket.generator.DefaultUniqueTicketIdGenerator;
 import org.maxkey.entity.Organizations;
 import org.maxkey.entity.SocialsProvider;
@@ -65,6 +71,9 @@ public class ThirdLoginController
     @Qualifier("socialSignOnProviderService")
     SocialSignOnProviderService socialSignOnProviderService;
 
+    @Autowired
+    SocialsAssociateService socialSignOnUserService;
+
     private DefaultUniqueTicketIdGenerator generator = new DefaultUniqueTicketIdGenerator();
 
     @Autowired
@@ -137,27 +146,30 @@ public class ThirdLoginController
         RedisConnection redisConnection = redisConnectionFactory.getConnection();
         String userInfo = redisConnection.get(token);
         Jackson2JsonRedisSerializer<UserInfo> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<UserInfo>(UserInfo.class);
-        UserInfo user = JSONObject.parseObject(userInfo,UserInfo.class);
-        result.put("token",token);
-        result.put("user",user);
-        redisConnection.setex(ticket, 60 * 60 * 24 * 1,JSON.toJSONString(user));
+        UserInfo user = JSONObject.parseObject(userInfo, UserInfo.class);
+        result.put("token", token);
+        result.put("user", user);
+        redisConnection.setex(ticket, 60 * 60 * 24 * 1, JSON.toJSONString(user));
         redisConnection.close();
         result = new JSONObject();
-        result.put("ticket",ticket);
+        result.put("ticket", ticket);
         return new RetResult().setMsg("请求成功").setData(result).setCode(RetCode.SUCCESS);
     }
 
     /**
      * 根据令牌获取用户信息
+     *
      * @param ticket
      * @return
      */
     @RequestMapping(value = {"/getUserInfo"}, method = RequestMethod.GET)
     public RetResult<Object> getUserInfo(@RequestParam("ticket") String ticket, HttpServletRequest request)
     {
-        if(StringUtils.isEmpty(ticket)){
+        if (StringUtils.isEmpty(ticket))
+        {
             return new RetResult().setMsg("参数ticket不存在").setData(null).setCode(RetCode.FAIL);
         }
+
         JSONObject result = new JSONObject();
         RedisConnection redisConnection = redisConnectionFactory.getConnection();
         String userInfo = redisConnection.get(ticket);
@@ -167,6 +179,52 @@ public class ThirdLoginController
     }
 
     /**
+     * 根据钉钉ID获取用户信息
+     *
+     * @param userid
+     * @return
+     */
+    @RequestMapping(value = {"/getUserInfoByDingId"}, method = RequestMethod.GET)
+    public RetResult<Object> getUserInfoByDingId(@RequestParam("userid") String userid, HttpServletRequest request)
+    {
+        if (StringUtils.isEmpty(userid))
+        {
+            return new RetResult().setMsg("参数ticket不存在").setData(null).setCode(RetCode.FAIL);
+        }
+        String accessToken = "";
+        try
+        {
+            accessToken = getAccessToken();
+        } catch (Exception e)
+        {
+
+        }
+        UserInfo info = userInfoService.getMapper().queryUserInfoByAssociateId(userid);
+        JSONObject result = new JSONObject();
+        result.put("userInfo", info);
+        result.put("accessToken", accessToken);
+        return new RetResult().setMsg("请求成功").setData(result).setCode(RetCode.SUCCESS);
+    }
+
+    /**
+     * 获取accessToken
+     *
+     * @return
+     * @throws ApiException
+     */
+    public String getAccessToken() throws ApiException
+    {
+        SocialsProvider socialSignOnProvider = socialSignOnProviderService.get("dingtalk");
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
+        OapiGettokenRequest request = new OapiGettokenRequest();
+        request.setAppkey(socialSignOnProvider.getClientId());
+        request.setAppsecret(socialSignOnProvider.getClientSecret());
+        request.setHttpMethod("GET");
+        OapiGettokenResponse response = client.execute(request);
+        return response.getAccessToken();
+    }
+
+    /**
      * 校验token
      *
      * @param token

+ 3 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/application-http.properties

@@ -74,6 +74,9 @@ maxkey.login.default.uri                        =appList
 maxkey.ipaddress.whitelist                      =false
 #notices show
 maxkey.notices.visible                          =false
+
+# call back url
+maxkey.callback.url                             = ${CALL_BACK_URL:${maxkey.server.uri}}
 ############################################################################
 #ssl configuration                                                         #
 ############################################################################