SocialsUserController.java 18 KB

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