ny
昨天 b6f169fe43a2b13f351aefc152374fc7f0bc8cb7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
package jnpf.permission.controller;
 
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.controller.SuperController;
import jnpf.config.ConfigValueUtil;
import jnpf.constant.MsgCode;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.exception.LoginException;
import jnpf.permission.SocialsUserApi;
import jnpf.permission.entity.SocialsUserEntity;
import jnpf.permission.entity.UserEntity;
import jnpf.permission.model.socails.SocialsUserInfo;
import jnpf.permission.model.socails.SocialsUserModel;
import jnpf.permission.model.socails.SocialsUserVo;
import jnpf.permission.service.SocialsUserService;
import jnpf.permission.service.UserService;
import jnpf.socials.config.CustomAuthConfig;
import jnpf.socials.config.SocialsConfig;
import jnpf.socials.enums.SocialsAuthEnum;
import jnpf.socials.model.AuthCallbackNew;
import jnpf.socials.utils.AuthSocialsUtil;
import jnpf.util.*;
import jnpf.util.wxutil.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.enums.AuthResponseStatus;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
 
/**
 * 单点登录
 *
 * @author JNPF开发平台组
 * @version V3.4.2
 * @copyright 引迈信息技术有限公司
 * @date 2022/7/14 10:48:00
 */
@Tag(name = "第三方登录和绑定", description = "Socials")
@RestController
@RequestMapping("/socials")
@Slf4j
public class SocialsUserController extends SuperController<SocialsUserService, SocialsUserEntity> implements SocialsUserApi {
    @Autowired
    private SocialsUserService socialsUserService;
    @Autowired
    private AuthSocialsUtil authSocialsUtil;
    @Autowired
    private UserService userService;
    @Autowired
    private SocialsConfig socialsConfig;
    @Autowired
    private ConfigValueUtil configValueUtil;
    @Autowired
    private RedisUtil redisUtil;
 
    /**
     * 获取用户列表
     *
     * @param
     * @return ignore
     */
    @Operation(summary = "获取用户授权列表")
    @Parameters({
            @Parameter(name = "userId", description = "用户id")
    })
    @GetMapping
    public ActionResult<List<SocialsUserVo>> getList(@RequestParam(value = "userId", required = false) String userId) {
        if (StringUtil.isEmpty(userId)) {
            userId = UserProvider.getUser().getUserId();
        }
        List<Map<String, Object>> platformInfos = SocialsAuthEnum.getPlatformInfos();
        String s = JSONArray.toJSONString(platformInfos);
        List<SocialsUserVo> socialsUserVos = JsonUtil.getJsonToList(s, SocialsUserVo.class);
        List<CustomAuthConfig> config = socialsConfig.getConfig();
        List<SocialsUserVo> res = new ArrayList<>();
        if (config == null) {
            return ActionResult.fail(MsgCode.PS019.get());
        }
        config.stream().forEach(item -> {
            socialsUserVos.stream().forEach(item2 -> {
                if (item2.getEnname().toLowerCase().equals(item.getProvider())) {
                    res.add(item2);
                }
            });
        });
        //查询绑定信息
        List<SocialsUserEntity> listByUserId = socialsUserService.getListByUserId(userId);
        List<SocialsUserModel> listModel = JsonUtil.getJsonToList(listByUserId, SocialsUserModel.class);
        res.stream().forEach(item -> {
            listModel.stream().forEach(item2 -> {
                if (item.getEnname().equals(item2.getSocialType())) item.setEntity(item2);
            });
        });
        return ActionResult.success(res);
    }
 
    /**
     * 绑定:重定向第三方登录页面
     *
     * @return ignore
     */
    @Operation(summary = "重定向第三方登录页面")
    @Parameters({
            @Parameter(name = "source", description = "地址", required = true)
    })
    @GetMapping("/render/{source}")
    @ResponseBody
    public ActionResult render(@PathVariable String source) {
        AuthRequest authRequest = authSocialsUtil.getAuthRequest(source, UserProvider.getUser().getUserId(), false, null, UserProvider.getUser().getTenantId());
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        return ActionResult.success(authorizeUrl);
    }
 
 
    /**
     * 设置租户库
     *
     * @param
     * @return
     * @copyright 引迈信息技术有限公司
     * @date 2022/9/8
     */
    private boolean setTenantData(String tenantId, UserInfo userInfo) {
        try{
            TenantDataSourceUtil.switchTenant(tenantId);
        }catch (Exception e){
            return false;
        }
        return true;
    }
 
    /**
     * 解绑
     *
     * @param userId 用户id
     * @param id 主键
     * @return ignore
     */
    @Operation(summary = "解绑")
    @Parameters({
            @Parameter(name = "userId", description = "用户id"),
            @Parameter(name = "id", description = "主键", required = true)
    })
    @DeleteMapping("/{id}")
    public ActionResult deleteSocials(@RequestParam(value = "userId",required = false)String userId,@PathVariable("id") String id) {
        SocialsUserEntity byId = socialsUserService.getById(id);
        UserInfo userInfo = UserProvider.getUser();
        boolean b = socialsUserService.removeById(id);
        if (b) {
            //多租户开启-解除绑定
            if (configValueUtil.isMultiTenancy()) {
                String param = "?userId=" + byId.getUserId() + "&tenantId=" + userInfo.getTenantId() + "&socialsType=" + byId.getSocialType();
                JSONObject object = HttpUtil.httpRequest(configValueUtil.getMultiTenancyUrl() + "socials" + param, "DELETE", null);
                if (object == null || "500".equals(object.get("code").toString()) || "400".equals(object.getString("code"))) {
                    return ActionResult.fail(MsgCode.PS018.get());
                }
            }
            return ActionResult.success(MsgCode.SU005.get());
        }
        return ActionResult.fail(MsgCode.PS018.get());
    }
 
 
    @GetMapping("/list")
    @NoDataSourceBind
    public List<SocialsUserVo> getLoginList(@RequestParam("ticket") String ticket) {
        if (!socialsConfig.isSocialsEnabled()) return null;
        List<Map<String, Object>> platformInfos = SocialsAuthEnum.getPlatformInfos();
        String s = JSONArray.toJSONString(platformInfos);
        List<SocialsUserVo> socialsUserVos = JsonUtil.getJsonToList(s, SocialsUserVo.class);
        List<CustomAuthConfig> config = socialsConfig.getConfig();
        List<SocialsUserVo> res = new ArrayList<>();
        config.stream().forEach(item -> {
            socialsUserVos.stream().forEach(item2 -> {
                if (item2.getEnname().toLowerCase().equals(item.getProvider())) {
                    AuthRequest authRequest = authSocialsUtil.getAuthRequest(item2.getEnname(), null, true, ticket, null);
                    String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
                    item2.setRenderUrl(authorizeUrl);
                    res.add(item2);
                }
            });
        });
        return res;
    }
 
    @GetMapping("/getSocialsUserInfo")
    @NoDataSourceBind
    public SocialsUserInfo getSocialsUserInfo(@RequestParam("source") String source, @RequestParam("code") String code,
                                              @RequestParam(value = "state", required = false) String state) throws LoginException {
        //获取第三方请求
        AuthCallbackNew callback = setAuthCallback(code, state);
        AuthRequest authRequest = authSocialsUtil.getAuthRequest(source, null, false, null, null);
        AuthResponse<AuthUser> res = authRequest.login(callback);
        if(AuthResponseStatus.FAILURE.getCode()==res.getCode()){
            throw new LoginException("连接失败!");
        }else if(AuthResponseStatus.SUCCESS.getCode()!=res.getCode()){
            throw new LoginException("授权失败:"+res.getMsg());
        }
        //登录用户第三方id
        String uuid = getSocialUuid(res);
        String socialName=StringUtil.isNotEmpty(res.getData().getUsername())?res.getData().getUsername():res.getData().getNickname();
        SocialsUserInfo socialsUserInfo = getUserInfo(source,  uuid, socialName);
        return socialsUserInfo;
    }
 
    /**
     * 获取用户绑定信息列表
     * @param
     * @return
     * @copyright 引迈信息技术有限公司
     * @date 2022/9/20
     */
    @NoDataSourceBind
    public SocialsUserInfo getUserInfo(String source, String uuid, String socialName) throws LoginException {
        SocialsUserInfo socialsUserInfo=new SocialsUserInfo();
        UserInfo userInfo = UserProvider.getLocalLoginUser();
        if(userInfo == null){
            userInfo = new UserInfo();
        }
        //查询租户绑定
        if ("wechat_applets".equals(source)) {
            source = "wechat_open";
        }
        if (configValueUtil.isMultiTenancy()) {
            JSONObject object = HttpUtil.httpRequest(configValueUtil.getMultiTenancyUrl() + "socials/list?socialsId=" + uuid, "GET", null);
            if (object == null || "500".equals(object.get("code").toString()) || "400".equals(object.getString("code"))) {
                throw new LoginException("租户绑定信息查询错误!");
            }
            if ("200".equals(object.get("code").toString())) {
                JSONArray data = JSONArray.parseArray(object.get("data").toString());
                int size = data.size();
                System.out.println(size);
                if (data == null || data.size() == 0) {
                    socialsUserInfo.setSocialUnionid(uuid);
                    socialsUserInfo.setSocialName(socialName);
                    return socialsUserInfo;
                } else if (data.size() == 1) {
                    //租户开启时-切换租户库
                    JSONObject oneUser = (JSONObject) data.get(0);
                    setTenantData(oneUser.get("tenantId").toString(), userInfo);
                    List<SocialsUserEntity> list = socialsUserService.getUserIfnoBySocialIdAndType(uuid, source);
                    if (CollectionUtil.isEmpty(list)) {
                        throw new LoginException("第三方未绑定账号!");
                    }
                    UserEntity infoById = userService.getInfo(list.get(0).getUserId());
                    BeanUtils.copyProperties(infoById, userInfo);
                    userInfo.setTenantId(oneUser.get("tenantId").toString());
                    userInfo.setUserId(infoById.getId());
                    userInfo.setUserAccount(userInfo.getTenantId() + "@" + infoById.getAccount());
                    socialsUserInfo.setTenantUserInfo(data);
                    socialsUserInfo.setUserInfo(userInfo);
                } else {
                    socialsUserInfo.setTenantUserInfo(data);
                }
            }
        } else {//非多租户
            //查询绑定
            List<SocialsUserEntity> list = socialsUserService.getUserIfnoBySocialIdAndType(uuid, source);
            if (CollectionUtil.isNotEmpty(list)) {
                UserEntity infoById = userService.getInfo(list.get(0).getUserId());
                BeanUtils.copyProperties(infoById, userInfo);
                userInfo.setUserId(infoById.getId());
                userInfo.setUserAccount(infoById.getAccount());
                socialsUserInfo.setUserInfo(userInfo);
            } else {
                socialsUserInfo.setSocialUnionid(uuid);
                socialsUserInfo.setSocialName(socialName);
            }
        }
        return socialsUserInfo;
    }
 
    /**
     * 绑定
     *
     * @return ignore
     */
    @GetMapping("/callback")
    @ResponseBody
    @NoDataSourceBind
    public JSONObject binding(@RequestParam("source") String source,
                              @RequestParam(value = "userId", required = false) String userId,
                              @RequestParam(value = "tenantId", required = false) String tenantId,
                              @RequestParam(value = "code", required = false) String code,
                              @RequestParam(value = "state", required = false) String state) {
        log.info("进入callback:" + source + " callback params:");
        //获取第三方请求
        AuthCallbackNew callback = setAuthCallback(code, state);
        //租户开启时-切换租户库
        if (configValueUtil.isMultiTenancy()) {
            boolean b = setTenantData(tenantId, new UserInfo());
            if (!b) {
                return resultJson(201, "查询租户信息错误!");
            }
 
        }
        //获取第三方请求
        AuthRequest authRequest = authSocialsUtil.getAuthRequest(source, userId, false, null, null);
        AuthResponse<AuthUser> res = authRequest.login(callback);
        log.info(JSONObject.toJSONString(res));
        if (res.ok()) {
            String uuid = getSocialUuid(res);
            List<SocialsUserEntity> userIfnoBySocialIdAndType = socialsUserService.getUserIfnoBySocialIdAndType(uuid, source);
            if (CollectionUtil.isNotEmpty(userIfnoBySocialIdAndType)) {
                UserEntity info = userService.getInfo(userIfnoBySocialIdAndType.get(0).getUserId());
                return resultJson(201, "当前账户已被" + info.getRealName() + "/" + info.getAccount() + "绑定,不能重复绑定");
            }
            SocialsUserEntity socialsUserEntity = new SocialsUserEntity();
            socialsUserEntity.setUserId(userId);
            socialsUserEntity.setSocialType(source);
            socialsUserEntity.setSocialName(res.getData().getUsername());
            socialsUserEntity.setSocialId(uuid);
            socialsUserEntity.setCreatorTime(new Date());
            boolean save = socialsUserService.save(socialsUserEntity);
 
            //租户开启时-添加租户库绑定数据
            if (configValueUtil.isMultiTenancy() && save) {
                JSONObject params = (JSONObject) JSONObject.toJSON(socialsUserEntity);
                UserEntity info = userService.getInfo(userId);
                params.put("tenantId", tenantId);
                params.put("account", info.getAccount());
                params.put("accountName", info.getRealName() + "/" + info.getAccount());
                JSONObject object = HttpUtil.httpRequest(configValueUtil.getMultiTenancyUrl() + "socials", "POST", params.toJSONString());
                if (object == null || "500".equals(object.get("code").toString()) || "400".equals(object.getString("code"))) {
                    return resultJson(201, "用户租户绑定错误!");
                }
            }
            return resultJson(200, "绑定成功!");
 
        }
        return resultJson(201, "第三方回调失败!");
    }
 
    /**
     * 设置第三方code state参数
     *
     * @param
     * @return
     * @copyright 引迈信息技术有限公司
     * @date 2022/9/8
     */
    private AuthCallbackNew setAuthCallback(String code, String state) {
        AuthCallbackNew callback = new AuthCallbackNew();
        callback.setAuthCode(code);
        callback.setAuth_code(code);
        callback.setAuthorization_code(code);
        callback.setCode(code);
        callback.setState(state);
        return callback;
    }
 
    /**
     * 返回json
     *
     * @param
     * @return
     * @copyright 引迈信息技术有限公司
     * @date 2022/9/8
     */
    private JSONObject resultJson(int code, String message) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", code);
        jsonObject.put("message", message);
        return jsonObject;
    }
    private String getSocialUuid(AuthResponse<AuthUser> res) {
        String uuid = res.getData().getUuid();
        if (res.getData().getToken() != null && StringUtil.isNotEmpty(res.getData().getToken().getUnionId())) {
            uuid = res.getData().getToken().getUnionId();
        }
        return uuid;
    }
 
    /**
     * 绑定
     *
     * @return ignore
     */
    @GetMapping("/loginbind")
    @ResponseBody
    @NoDataSourceBind
    public void loginAutoBinding(@RequestParam("socialType") String socialType,
                                 @RequestParam("socialUnionid") String socialUnionid,
                                 @RequestParam("socialName") String socialName,
                                 @RequestParam("userId") String userId,
                                 @RequestParam(value = "tenantId", required = false) String tenantId) {
        //查询租户绑定
        if ("wechat_applets".equals(socialType)) {
            socialType = "wechat_open";
        }
        //租户开启时-切换租户库
        if (configValueUtil.isMultiTenancy()) {
            setTenantData(tenantId, new UserInfo());
        }
        List<SocialsUserEntity> list = socialsUserService.getListByUserIdAndSource(userId, socialType);
        if(CollectionUtil.isNotEmpty(list)){//账号已绑定该第三方其他账号,则不绑定
            return;
        }
        SocialsUserEntity socialsUserEntity = new SocialsUserEntity();
        socialsUserEntity.setUserId(userId);
        socialsUserEntity.setSocialType(socialType);
        socialsUserEntity.setSocialName(socialName);
        socialsUserEntity.setSocialId(socialUnionid);
        socialsUserEntity.setCreatorTime(new Date());
        boolean save = socialsUserService.save(socialsUserEntity);
        //租户开启时-添加租户库绑定数据
        if (configValueUtil.isMultiTenancy() && save) {
            JSONObject params = (JSONObject) JSONObject.toJSON(socialsUserEntity);
            UserEntity info = userService.getInfo(userId);
            params.put("tenantId", tenantId);
            params.put("account", info.getAccount());
            params.put("accountName", info.getRealName() + "/" + info.getAccount());
            JSONObject object = HttpUtil.httpRequest(configValueUtil.getMultiTenancyUrl() + "socials", "POST", params.toJSONString());
 
        }
    }
 
    /**
     *  根据第三方账号账号类型和id获取用户第三方绑定信息
     * @param socialId 第三方账号id
     * @return
     */
    @Override
    @GetMapping("/getInfoBySocialId")
    public SocialsUserEntity getInfoBySocialId(@RequestParam("socialId") String socialId, @RequestParam("socialType") String socialType){
        return socialsUserService.getInfoBySocialId(socialId, socialType);
    }
}