johnswang
2022-10-28 077dbf464f513ead41abf6e0103eafbe4286dd2c
提交 | 用户 | age
a6a76f 1 package com.yc.sdk.oauth2.action;
F 2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.UUID;
6 import java.util.concurrent.TimeUnit;
7
8 import javax.servlet.http.HttpServletRequest;
9 import javax.servlet.http.HttpServletResponse;
10 import javax.servlet.http.HttpSession;
11
12 import org.springframework.beans.factory.annotation.Autowired;
13 import org.springframework.data.redis.core.RedisTemplate;
14 import org.springframework.stereotype.Controller;
15 import org.springframework.web.bind.annotation.RequestMapping;
16
17 import com.qq.connect.QQConnectException;
18 import com.qq.connect.api.OpenID;
19 import com.qq.connect.api.qzone.UserInfo;
20 import com.qq.connect.javabeans.AccessToken;
21 import com.qq.connect.javabeans.qzone.UserInfoBean;
22 import com.qq.connect.oauth.Oauth;
23 import com.riversoft.weixin.common.oauth2.OpenUser;
24 import com.riversoft.weixin.common.user.Gender;
25 import com.yc.action.BaseAction;
26 import com.yc.entity.AttachmentConfig;
27 import com.yc.entity.UserAccountEntity;
28 import com.yc.exception.CallBackMessage;
29 import com.yc.multiData.SpObserver;
30 import com.yc.sdk.oauth2.entity.OAuth2InfoEntity;
31 import com.yc.sdk.oauth2.service.OAuth2UserIfc;
32 import com.yc.sdk.password.action.ChangePassword;
33 import com.yc.sdk.shopping.util.SettingKey;
34 import com.yc.sdk.weixincp.util.AvatarFile;
35 import com.yc.sdk.weixincp.util.RandomString;
36 import com.yc.service.user.UserAccountServiceIfc;
37 import com.yc.utils.SessionKey;
38
39 import me.chanjar.weixin.common.util.http.URIUtil;
40
41 @Controller
42 public class OAuth2ForQQ extends BaseAction {
43     
44     @Autowired 
45     private OAuth2UserIfc oauth2UserIfc;
46     @Autowired
47     private UserAccountServiceIfc userAccountService;
48     @SuppressWarnings("rawtypes")
49     @Autowired
50     RedisTemplate redisTemplate ;
51
52     protected static String oauth2HostName  = AttachmentConfig.get("Oauth2.HostName") ;
53     
54     @SuppressWarnings("unchecked")
55     @RequestMapping("/oauth2/qq.do")
56     public void action(HttpServletRequest request, HttpServletResponse response) {
57         response.setContentType("text/html;charset=utf-8");
58         HttpSession session = request.getSession();
59         String code = request.getParameter("code") ;
60         String dbid = request.getParameter(SessionKey.DATA_BASE_ID) ;
61         String hostUrl = SettingKey.getHostUrl(request) ;  //取当前原始主机名, 
62         CallBackMessage callBackMessage=new CallBackMessage();
63         
64         String redirect = request.getParameter("redirect"); // 登录后重定向页面,Added by Johns Wang, 2016-02-17
65         if (redirect != null && !"".equals(redirect)) redirect = URIUtil.encodeURIComponent(redirect);
66         if (code == null || "".equals(code)) {
67             String oauth2UUID = UUID.randomUUID().toString().toUpperCase();//生成uuid 
68             String orgHost = request.getParameter("orghost") ;
69             
70             String authorizationUserCode = request.getParameter(SessionKey.OAUTH2AuthorizationUserCode) ;
71             try {
72                 if (authorizationUserCode!=null && !"".equals(authorizationUserCode) && authorizationUserCode.length() > 50) {
73                     authorizationUserCode = ChangePassword.getDecryptPassword(authorizationUserCode);
74                 }
75             }catch (Exception e) {
76                 e.printStackTrace();
77                 System.out.println(this.getClass()+ " :参数" +SessionKey.OAUTH2AuthorizationUserCode + " 解密错误");
78                 this.print(response, callBackMessage.sendErrorMessage("错误:"+ (e.getCause()!=null?e.getCause().getMessage(): e.getMessage())));
79                 return ;
80             }
81             
82             
83             String dialogUrl = "" ;
84             try {
2cc5c2 85                 dialogUrl = new Oauth(request).getAuthorizeURL(request) ;
a6a76f 86             } catch (QQConnectException e) {
F 87                 e.printStackTrace();
88                 this.print(response, callBackMessage.sendErrorMessage("错误:"+ (e.getCause()!=null?e.getCause().getMessage(): e.getMessage())));
89                 return ;
aabaa3 90             }catch (Exception e) {
J 91                 e.printStackTrace();
92                 this.print(response, callBackMessage.sendErrorMessage("错误:"+ (e.getCause()!=null?e.getCause().getMessage(): e.getMessage())));
93                 return ;
a6a76f 94             }
F 95             //将关键信息保存到 redis 集群中,以确保数据交换时的信息安全 
96             OAuth2InfoEntity oauth2InfoEntity = new OAuth2InfoEntity() ;
97             oauth2InfoEntity.setDbid(dbid);
98             oauth2InfoEntity.setOrgHost(orgHost);
99             oauth2InfoEntity.setRedirect(redirect);
100             oauth2InfoEntity.setOauth2From("qq");
101             oauth2InfoEntity.setAuthorizationUserCode(authorizationUserCode);
102             try {
103                 //将 OAuth2InfoEntity 对象保存到 redis 服务器中 ,保留 1800秒 ,30分钟
104                 redisTemplate.delete(oauth2UUID) ;
105                 redisTemplate.opsForValue().set(oauth2UUID, oauth2InfoEntity, 1800, TimeUnit.SECONDS);
106                 boolean result = true ; 
107                 if (!result) {
108                     this.print(response, callBackMessage.sendErrorMessage("写入 redis 集群服务时出错,请检查集群服务配置!"));
109                     return ;
110                 }
111                 session.setAttribute(SessionKey.OAUTH2UUID, oauth2UUID);
112             }catch(Exception e) {
113                 e.printStackTrace();
114                 this.print(response, callBackMessage.sendErrorMessage (e.getCause()!=null?e.getCause().getMessage(): e.getMessage()));
115                 return ;
116             }
117             
118             try {
119                 response.sendRedirect(dialogUrl);
120             } catch (IOException e) {
121                 e.printStackTrace();
122                 this.print(response, callBackMessage.sendErrorMessage (e.getCause()!=null?e.getCause().getMessage(): e.getMessage()));
123                 return ;
124             }
125
126             //this.print(response, "<script> top.location.href='" + dialogUrl + "'</script>");
127             callBackMessage.setRedirect(dialogUrl);
128             this.print(response,  callBackMessage.toString() );
129             return ;
130         }
131         
132         
133         //String state = request.getParameter("state");
134         //String rand = (String)session.getAttribute("state") ;
135         try {
136             //配置信息保存在 qqconnectconfig.properties 文件中
2cc5c2 137             AccessToken accessTokenObj = (new Oauth(request)).getAccessTokenByRequest(request);
a6a76f 138             if (accessTokenObj.getAccessToken().equals("")) {
F 139                 //我们的网站被CSRF攻击了或者用户取消了授权
140                 //做一些数据统计工作  没有获取到响应参数
141                 this.print(response, callBackMessage.sendErrorMessage("登录异常,拉取用户信息失败,请检查拉取用户的域名和QQ connect中设置是否一致!"));
142                 return ;
143             }else{
144                 String oauth2UUID = (session.getAttribute(SessionKey.OAUTH2UUID)==null?"":(String)session.getAttribute(SessionKey.OAUTH2UUID));  //request.getParameter("uuid") ;
145                 if (oauth2UUID == null || "".equals(oauth2UUID)) {
146                     this.print(response, callBackMessage.sendErrorMessage("非法访问!"));
147                     return ;
148                 }
149                 
150                 OAuth2InfoEntity oauth2InfoEntity = null ;
151                 try{
152                     //从 redis 服务器中取出 OAuth2InfoEntity 对象
153                     oauth2InfoEntity = (OAuth2InfoEntity) redisTemplate.opsForValue().get(oauth2UUID) ;
154                 }catch(Exception e) {
155                     e.printStackTrace();
156                     this.print(response, callBackMessage.sendErrorMessage (e.getCause()!=null?e.getCause().getMessage(): e.getMessage()));
157                     return ;
158                 }
159                 if (oauth2InfoEntity == null) {
160                     this.print(response, callBackMessage.sendErrorMessage("从redis服务器获取原始主机信息失败,请检查【"+(oauth2HostName==null?"":oauth2HostName) +"】与当前登录主机是否使用同一个redis集群服务"));
161                     return ;
162                 }
163                 
164                 String orgHost = oauth2InfoEntity.getOrgHost();   //原始主机名 
165                 if (orgHost == null || "".equals(orgHost)) {
166                     this.print(response, callBackMessage.sendErrorMessage("非法原始主机名"));
167                     return ;
168                 }
169
170                 String accessToken = null,openId = null; 
171                 //long tokenExpireIn = 0L;
172                 
173                 accessToken = accessTokenObj.getAccessToken();
174                 //tokenExpireIn = accessTokenObj.getExpireIn();
175                 
176                 //session.setAttribute("demo_access_token", accessToken);
177                 //session.setAttribute("demo_token_expirein", String.valueOf(tokenExpireIn));
178
179                 
180                 // 利用获取到的accessToken 去获取当前用的openid -------- start
181                 OpenID openIDObj =  new OpenID(accessToken);
182                 openId = openIDObj.getUserOpenID();
183                 //PrintWriter out = response.getWriter();
184                 
185                 //out.println("欢迎你,代号为 " + openID + " 的用户!"+"<br/>");
077dbf 186                 UserInfo qzoneUserInfo = new UserInfo(accessToken, openId,request);
a6a76f 187                 UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
F 188                 if (userInfoBean.getRet() == 0) {
189                     String dbId = oauth2InfoEntity.getDbid(); 
190                     
191                     try {
192                         SpObserver.setDBtoInstance("_" + dbId);// 切换数据源
193                         
194                         OpenUser openUser = new OpenUser() ;
195                         openUser.setOpenId(openId);
196                         openUser.setHeadImgUrl(userInfoBean.getAvatar().getAvatarURL100());
197                         openUser.setNickName(userInfoBean.getNickname());
198                         int genderCode = 0 ;
199                         if (userInfoBean.getGender()!=null&&"男".equals(userInfoBean.getGender())) genderCode = 1 ;
200                         if (userInfoBean.getGender()!=null&&"女".equals(userInfoBean.getGender())) genderCode = 2 ;
201                         
202                         openUser.setSex(Gender.fromCode(genderCode));
203                         
204                         OpenUser erpOpenUser =  oauth2UserIfc.getOpenUserFromQQ(openId) ;
205                         if (erpOpenUser == null) {
206                             //保存新用户
207                             erpOpenUser = oauth2UserIfc.saveQQUser(openUser) ;
208                         }
209
210                         //更新头像
211                         if (erpOpenUser != null && openUser.getHeadImgUrl() != null && 
212                                 (!openUser.getHeadImgUrl().equals(erpOpenUser.getHeadImgUrl())
213                                         || erpOpenUser.getAvatarUnid()==null 
214                                         || erpOpenUser.getAvatarUnid().equals("") )) {
215                             String filePath = session.getServletContext().getRealPath("/")
216                                     + "uploads" + File.separator + "smallpic" + File.separator;
217                             String fileName = RandomString.getRandomString(8) + ".jpg";
218                             File file = AvatarFile.getAvatarFile(openUser.getHeadImgUrl(), fileName, filePath); // 获取微信图像
219                             oauth2UserIfc.saveQQUserAvator(openUser, Integer.valueOf(dbId), file) ;// 上传图像文件至数据库
220                         }
221                         
222                         oauth2InfoEntity.setOpenId(openId);
223                         oauth2InfoEntity.setNickName(userInfoBean.getNickname());
224                         oauth2InfoEntity.setHeadimgurl(userInfoBean.getAvatar().getAvatarURL100());
225                         try {
226                             //将 OAuth2InfoEntity 对象保存到 redis 服务器中 ,保留 1800秒 ,30分钟
227                             redisTemplate.delete(oauth2UUID) ;
228                             redisTemplate.opsForValue().set(oauth2UUID, oauth2InfoEntity, 1800, TimeUnit.SECONDS);
229                             boolean result = true ;
230                             if (!result) {
231                                 this.print(response,callBackMessage.sendErrorMessage( "写入 redis 集群服务时出错,请检查集群服务配置!"));
232                                 return ;
233                             }
234                         }catch(Exception e) {
235                             e.printStackTrace();
236                             this.print(response,callBackMessage.sendErrorMessage (e.getCause() !=null?e.getCause().getMessage(): e.getMessage()));
237                             return ;
238                         }
239                         
240                         //根据扫码openid 获取用户信息
241                         UserAccountEntity userAccount = userAccountService.getUserInfoByOauth2OpenIdForQQ(openId);
242                         //直接登录
243                         String goUrl = orgHost+"/oauth2/login.do?"+SessionKey.OAUTH2UUID+"="+ oauth2UUID;
244                         if (userAccount==null) {  
245                             if (oauth2InfoEntity!=null && oauth2InfoEntity.getAuthorizationUserCode()!=null&&!"".equals(oauth2InfoEntity.getAuthorizationUserCode())) {
246                                 //直接绑定用户名
247                                 oauth2UserIfc.saveOpenIdToUserCodeForQQ(oauth2InfoEntity.getAuthorizationUserCode(),openId) ;
248 //                                this.print(response,  callBackMessage.sendSuccessMessage("绑定QQ用户成功,请使用QQ扫码登录!"));
249                                 this.print(response, "<div style=\"color: #1eac4a;text-align: center;margin-top: 100px;\">绑定QQ用户成功,请使用QQ扫码登录!</div>");
250                                 return ;
251                             }else {
252                                 //绑定用户名,然后再登录
253                                 goUrl = hostUrl + "/oauth2/buildinguser.jsp?"+SessionKey.OAUTH2UUID+"="+ oauth2UUID+"&oauth2from=qq" ;
254                             }
255                         }
256                         response.sendRedirect(goUrl) ;
257                         return ;
258                     }catch (Exception e) {
259                         throw e ;
260                     }finally {
261                         SpObserver.setDBtoInstance();
262                     }
263                     
264                     
265                     
266                     /*
267                     out.println(userInfoBean.getNickname() + "<br/>");
268                     out.println(userInfoBean.getGender() + "<br/>");
269                     out.println("黄钻等级: " + userInfoBean.getLevel() + "<br/>");
270                     out.println("会员 : " + userInfoBean.isVip() + "<br/>");
271                     out.println("黄钻会员: " + userInfoBean.isYellowYearVip() + "<br/>");
272                     out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL30() + "/><br/>");
273                     out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL50() + "/><br/>");
274                     out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL100() + "/><br/>");*/
275                 } else {
276                     this.print(response,  callBackMessage.sendErrorMessage("很抱歉,我们没能正确获取到您的QQ信息,原因是: " + userInfoBean.getMsg()));
277                     return ;
278                 }
279             }
280         } catch (QQConnectException | IOException e) {
281             e.printStackTrace();
282             this.print(response, callBackMessage.sendErrorMessage((e.getCause() !=null?e.getCause().getMessage(): e.getMessage())));
283         }catch (Exception e) {
284             e.printStackTrace();
285             this.print(response,callBackMessage.sendErrorMessage( (e.getCause() !=null?e.getCause().getMessage(): e.getMessage())));
286         }
287     }
288
289 }