From 7ea8d1c6da749da69516f47593ae47546a0d3d4c Mon Sep 17 00:00:00 2001 From: xuhy <3313886187@qq.com> Date: 星期一, 16 十二月 2024 11:36:46 +0800 Subject: [PATCH] 微信登陆 --- applet/src/main/java/com/jilongda/applet/controller/LoginController.java | 449 ++++--------------------------------------------------- 1 files changed, 34 insertions(+), 415 deletions(-) diff --git a/applet/src/main/java/com/jilongda/applet/controller/LoginController.java b/applet/src/main/java/com/jilongda/applet/controller/LoginController.java index f88cabb..a3f06ce 100644 --- a/applet/src/main/java/com/jilongda/applet/controller/LoginController.java +++ b/applet/src/main/java/com/jilongda/applet/controller/LoginController.java @@ -1,30 +1,15 @@ package com.jilongda.applet.controller; -import com.alibaba.fastjson.JSONObject; -import com.alipay.v3.ApiException; -import com.aliyuncs.exceptions.ClientException; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.dingtalk.api.DefaultDingTalkClient; -import com.dingtalk.api.DingTalkClient; -import com.dingtalk.api.request.OapiUserGetuserinfoRequest; -import com.dingtalk.api.request.OapiV2UserGetRequest; -import com.dingtalk.api.response.OapiUserGetuserinfoResponse; -import com.dingtalk.api.response.OapiV2UserGetResponse; -import com.github.xiaoymin.knife4j.core.util.StrUtil; -import com.jilongda.applet.dto.*; -import com.jilongda.applet.model.SecUser; -import com.jilongda.applet.security.SecurityUserDetails; -import com.jilongda.applet.security.SysUserDetailsService; -import com.jilongda.applet.service.SecUserService; -import com.jilongda.applet.utils.ALiSendSms; -import com.jilongda.applet.utils.LoginInfoUtil; -import com.jilongda.applet.utils.dingding.DingTalkAccessTokenRequest; +import com.jilongda.applet.model.TAppUser; +import com.jilongda.applet.service.TAppUserService; +import com.jilongda.applet.wx.body.resp.Code2SessionRespBody; +import com.jilongda.applet.wx.body.resq.Code2SessionResqBody; +import com.jilongda.applet.wx.pojo.AppletUserDecodeData; +import com.jilongda.applet.wx.pojo.AppletUserEncrypteData; +import com.jilongda.applet.wx.utils.WeixinProperties; +import com.jilongda.applet.wx.utils.WxAppletTools; +import com.jilongda.applet.wx.utils.WxUtils; import com.jilongda.common.basic.ApiResult; -import com.jilongda.common.basic.Constant; -import com.jilongda.common.exception.ServiceException; -import com.jilongda.common.log.OperLoginLog; -import com.jilongda.common.log.OperationLog; -import com.jilongda.common.msg.HuaweiCloudSMSUtil; import com.jilongda.common.redis.RedisAutoTemplate; import com.jilongda.common.security.SecurityUtils; import com.jilongda.common.utils.WebUtils; @@ -33,16 +18,11 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; -import java.util.HashMap; import java.util.Map; -import java.util.Objects; /** * <p> @@ -57,303 +37,35 @@ @RestController @RequestMapping("/") public class LoginController { - private final SecurityUtils securityUtils; - private final AuthenticationManager authenticationManager; - private final RedisAutoTemplate redisAutoTemplate; - private final HuaweiCloudSMSUtil msgUtils; - private final LoginInfoUtil loginInfoUtil; - private final SysUserDetailsService loadUserDetailsService; @Autowired - private SecUserService secUserService; + private SecurityUtils securityUtils; @Autowired - private PasswordEncoder passwordEncoder; - + private AuthenticationManager authenticationManager; @Autowired - public LoginController(SecurityUtils securityUtils, AuthenticationManager authenticationManager, RedisAutoTemplate redisAutoTemplate, HuaweiCloudSMSUtil msgUtils, LoginInfoUtil loginInfoUtil,SysUserDetailsService loadUserDetailsService) { - this.securityUtils = securityUtils; - this.authenticationManager = authenticationManager; - this.redisAutoTemplate = redisAutoTemplate; - this.msgUtils = msgUtils; - this.loginInfoUtil = loginInfoUtil; - this.loadUserDetailsService = loadUserDetailsService; - } + private RedisAutoTemplate redisAutoTemplate; + @Autowired + private TAppUserService appUserService; + @Autowired + private WeixinProperties wxConfig; + @Autowired + private RestTemplate wxRestTemplate; -// @ApiOperation(value = "通过code获得openid") -// @GetMapping("openId-by-jscode2session/{code}") -// public ApiResult<Map<String, Object>> jscode2session(@PathVariable("code") String code) { -//// log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", code); -//// WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig); -//// Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(code)); -//// String openid = body.getOpenid(); -//// String sessionKey = body.getSessionKey(); -//// SecUser secUser = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class).eq(SecUser::getOpenId, openid).last("limit 1")); -//// if (Objects.isNull(secUser)) { -//// return ApiResult.failed(500, "请绑定账号"); -//// } -//// // 提前对sessionKey进行删除 -//// //redisTemplate.delete(openid); -//// log.info("换取sessionKey:{}", sessionKey); -//// // 将sessionKey进行存储,后续获取信息需要 -//// redisAutoTemplate.setStr(openid, sessionKey); -// Map<String, Object> tokenInfos = securityUtils.login(null, null, authenticationManager, SecUser.class, 3); -// return ApiResult.success(tokenInfos); -// } - -// @ApiOperation(value = "账号与小程序进行绑定") -// @GetMapping("openidBindPhone/{code}/{account}") -// public ApiResult<String> openidBindPhone(@PathVariable("code") String code, @PathVariable("account") String account) { -// SecUser secUser = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class).eq(SecUser::getAccount, account).last("limit 1")); -// Assert.isTrue(!StringUtils.hasLength(secUser.getOpenId()), "该账号已绑定微信"); -// log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", code); -// WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig); -// Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(code)); -// String openid = body.getOpenid(); -// // 手机号绑定微信 -// secUser.setOpenId(openid); -// secUserService.updateById(secUser); -// return ApiResult.success(); -// } - /** - * 登录接口 - */ -// @OperLoginLog -// @ApiOperation("用户账号登录") -// @PostMapping(value = "login") -// public ApiResult<Map<String, Object>> login(@Validated @RequestBody LoginDTO loginDto) { -// // 先检验是否登录 -// String username = loginDto.getAccount(); -// String password = loginDto.getPassword(); -// -// log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", loginDto.getCode()); -//// WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig); -//// Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(loginDto.getCode())); -//// String openid = body.getOpenid(); -//// loginDto.setOpenId(openid); -// -// try { -// Map<String, Object> token = securityUtils.login(username, password, authenticationManager, SecurityUserDetails.class, 2); -// return ApiResult.success(token); -// } catch (Exception e) { -// e.printStackTrace(); -// ApiResult<Map<String, Object>> failed = ApiResult.failed(new HashMap<>(1)); -// failed.setCode(0); -// failed.setSuccess(false); -// failed.setMsg(e.getMessage()); -// return failed; -// } -// } - - /** - * 登录接口 - */ - @OperLoginLog - @ApiOperation("后台登录") - @PostMapping(value = "login") - public ApiResult<Map<String, Object>> login1(@Validated @RequestBody LoginDTO loginDto) { - //验证是否通过验证 -// if (ObjectUtils.isEmpty(loginDto.getVerify()) || !loginDto.getVerify()) { -// ApiResult<Map<String, Object>> failed = new ApiResult<>(); -// failed.setMsg("登录失败,请正确验证!"); -// return failed; -// } - // 先检验是否登录 - String username = loginDto.getPhone(); - String password = loginDto.getPassword(); - try { - SecUser secUser = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class) - .eq(SecUser::getAccount, loginDto.getPhone())); - Assert.isTrue(Objects.nonNull(secUser), "该账号不存在"); - - - SecUser one = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class).eq(SecUser::getAccount, username)); - if (one.getState()){ - return ApiResult.failed(500, "该账号已被冻结,请联系管理员"); - } - - - Map<String, Object> token = securityUtils.login(username, password, authenticationManager, SecurityUserDetails.class, 1); - return ApiResult.success(token); - } catch (Exception e) { - ApiResult<Map<String, Object>> failed = ApiResult.failed(new HashMap<>(1)); - failed.setCode(0); - failed.setSuccess(false); - failed.setMsg(e.getMessage()); - return failed; + @ApiOperation(value = "通过code获得openid,获取用户信息",tags = {"微信小程序登录"}) + @PostMapping("/openIdByJsCode") + public ApiResult<Map<String, Object>> openIdByJsCode(@RequestBody AppletUserEncrypteData data) { + log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", data.getCode()); + WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisAutoTemplate); + Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(data.getCode())); + String openid = body.getOpenid(); + String sessionKey = body.getSessionKey(); + if(!StringUtils.hasLength(data.getEncryptedData()) || !StringUtils.hasLength(data.getIv())){ + return ApiResult.failed("已拒绝授权",null); } - } - - /** - * 登录接口 - */ -// @OperLoginLog -// @ApiOperation("选择用户账号登录") -// @PostMapping(value = "choose-login") -// public ApiResult<Map<String, Object>> chooseLogin(@Validated @RequestBody LoginDTO loginDto) { - // 先检验是否登录 -// String username = loginDto.getAccount(); -// -//// SecUser one = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class) -//// .eq(SecUser::getAccount, username)); -// -// log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", loginDto.getCode()); -// WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig); -// Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(loginDto.getCode())); -// String openid = body.getOpenid(); -// loginDto.setOpenId(openid); -// -// try { -// Map<String, Object> token = securityUtils.login(username, one, authenticationManager, SecUser.class, 2); -// -// //保存登录记录 -// try { -// loginRecordService.saveNew((SecurityUserDetails) token.get("userInfo")); -// } catch (Exception e) { -// log.error("登录记录失败!"); -// } -// -// return ApiResult.success(token); -// } catch (Exception e) { -// ApiResult<Map<String, Object>> failed = ApiResult.failed(new HashMap<>(1)); -// failed.setCode(0); -// failed.setSuccess(false); -// failed.setMsg(e.getMessage()); -// return failed; -// } -// return ApiResult.success(new HashMap<>()); -// } - - /** - * 登录接口 - */ -// @ApiOperation("短信登录") -// @PostMapping(value = "code/login") -// public ApiResult<List<SecUser>> loginByCode(@Validated @RequestBody LoginCodeDTO dto) { -// // 先检验是否登录 -// String phone = dto.getPhone(); -// String code = dto.getCode(); -// // 校验验证码是否正确 -// String redisCode = redisAutoTemplate.getStr(dto.getPhone()); -// Assert.isTrue(StringUtils.hasLength(redisCode), "验证码已过期"); -// if (!code.equals(redisCode)) { -// throw new ServiceException(500, "验证码错误,请重新输入验证码!"); -// } -// try { -//// List<SecUser> list = secUserService.list(Wrappers.lambdaQuery(SecUser.class) -//// .eq(SecUser::getPhone, phone)); -//// list = list.stream().filter(o -> !o.getShortName().contains("admin")).collect(Collectors.toList()); -//// Map<String, Object> token = securityUtils.login(phone, code, authenticationManager, SecurityUserDetails.class, true); -// //保存登录记录 -// return ApiResult.success(new ArrayList<>()); -// } catch (Exception e) { -// ApiResult<List<SecUser>> failed = ApiResult.failed(new ArrayList<>(1)); -// failed.setCode(0); -// failed.setSuccess(false); -// failed.setMsg(e.getMessage()); -// return failed; -// } -// } - - @ApiOperation("发送验证码") - @PostMapping(value = "sendCode") - public ApiResult<String> sendCode(@RequestBody VerificationCodeDTO dto) throws ClientException { - - // 账号查询用户 - SecUser secUser = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class) - .eq(SecUser::getAccount, dto.getPhone())); - Assert.isTrue(Objects.nonNull(secUser), "该账号不存在"); - - // 发送验证码并存储到redis - if (StringUtils.hasLength(dto.getPhone())) { - if(!loginInfoUtil.checkPhoneExits(dto.getPhone())){ - throw new ServiceException("无效手机号码"); - } - String code = String.valueOf((int) (Math.random() * 1000000)); - //TODO 临时验证码,短信未开通前测试用 -// code = "666666"; - redisAutoTemplate.setStr("code:"+dto.getPhone(), code); - redisAutoTemplate.expire(dto.getPhone(), Constant.REDIS_EXPIRE); -// msgUtils.sendSMS(dto.getPhone(), code); - - AliSms aliSms =new AliSms(); - aliSms.setCode(code); - aliSms.setProduct(dto.getPhone()); - String json = JSONObject.toJSONString(aliSms); - aLiSendSms.sendSms(dto.getPhone(), "SMS_58880127", json); - - return ApiResult.success("发送短信验证码成功!15分钟内有效"); - } - return ApiResult.failed(500, "发送短信验证码失败,请确认手机号码!"); - } - - - @ApiOperation("发送修改密码验证码") - @PostMapping(value = "sendPassCode") - public ApiResult<String> sendPassCode(@RequestBody VerificationCodeDTO dto) throws ClientException { - - // 账号查询用户 - SecUser secUser = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class) - .eq(SecUser::getAccount, dto.getPhone())); - Assert.isTrue(Objects.nonNull(secUser), "该账号不存在"); - - // 发送验证码并存储到redis - if (StringUtils.hasLength(dto.getPhone())) { - if(!loginInfoUtil.checkPhoneExits(dto.getPhone())){ - throw new ServiceException("无效手机号码"); - } - String code = String.valueOf((int) (Math.random() * 1000000)); - //TODO 临时验证码,短信未开通前测试用 -// code = "666666"; - redisAutoTemplate.setStr("code:"+dto.getPhone(), code); - redisAutoTemplate.expire(dto.getPhone(), Constant.REDIS_EXPIRE); -// msgUtils.sendSMS(dto.getPhone(), code); - - AliSms aliSms =new AliSms(); - aliSms.setCode(code); - aliSms.setProduct(dto.getPhone()); - String json = JSONObject.toJSONString(aliSms); - aLiSendSms.sendSms(dto.getPhone(), "SMS_58880123", json); - - return ApiResult.success("发送短信验证码成功!15分钟内有效"); - } - return ApiResult.failed(500, "发送短信验证码失败,请确认手机号码!"); - } - - - @OperLoginLog - @ApiOperation("短信登录") - @PostMapping(value = "code/login") - public ApiResult<Map<String, Object>> loginByCode(@Validated @RequestBody LoginCodeDTO dto) { - String phone = dto.getPhone(); - String code = dto.getCode(); - // 校验验证码是否正确 - if(!redisAutoTemplate.hasKey("code:"+phone)){ - throw new ServiceException(500, "验证码错误"); - } - String redisCode = redisAutoTemplate.getStr("code:"+phone); - if (!code.equals(redisCode)) { - throw new ServiceException(500, "验证码错误"); - } - try { - - SecUser one = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class).eq(SecUser::getAccount, phone)); - if (Objects.isNull(one)){ - return ApiResult.failed(500, "请输入正确的账号"); - } - if (one.getState()){ - return ApiResult.failed(500, "该账号已被冻结,请联系管理员"); - } - - Map<String, Object> token = securityUtils.login(phone, code, authenticationManager, SecurityUserDetails.class, 2); - SecurityUserDetails userDetails = loadUserDetailsService.loadUserByUsername(phone); - token.put("userInfo", userDetails); - return ApiResult.success(token); - } catch (Exception e) { - ApiResult<Map<String, Object>> failed = ApiResult.failed(new HashMap<>(1)); - failed.setCode(0); - failed.setSuccess(false); - failed.setMsg(e.getMessage()); - return failed; - } + AppletUserDecodeData appletUserDecodeData = WxUtils.encryptedData(data.getEncryptedData(), sessionKey, data.getIv()); + appletUserDecodeData.setOpenId(openid); + appUserService.wxLogin(appletUserDecodeData); + Map<String, Object> tokenInfos = securityUtils.login(null, null, authenticationManager, TAppUser.class, 3); + return ApiResult.success(tokenInfos); } @ApiOperation("退出登录") @@ -365,99 +77,6 @@ } return ApiResult.success(); } - - @OperationLog(operType = "修改", operDesc = "密码修改", operModul = "用户") - @ApiOperation("首页密码修改") - @PostMapping("/pageResetPassword") - public ApiResult<String> pageResetPassword(@Validated @RequestBody ResetPasswordDTO dto) { - // 账号查询用户 - SecUser secUser = secUserService.getOne(Wrappers.lambdaQuery(SecUser.class) - .eq(SecUser::getPhone, dto.getPhone())); - Assert.isTrue(Objects.nonNull(secUser), "该账号不存在"); - - // 校验短信验证码 - String str = redisAutoTemplate.getStr("code:"+secUser.getPhone()); - if(!StringUtils.hasLength(str)){ - return ApiResult.failed("验证码已过期!"); - } - if(!str.equals(dto.getCode())){ - return ApiResult.failed("验证码错误"); - } - -// if (StrUtil.isNotBlank(dto.getPassword())) { -// // 根据加密算法加密用户输入的密码,然后和数据库中保存的密码进行比较 -// if (!this.passwordEncoder.matches(dto.getOldPassword(), secUser.getPassword())) { -// throw new BadCredentialsException("输入原密码不正确"); -// } - // 修改密码 - secUser.setPassword(passwordEncoder.encode(dto.getPassword())); -// } else { -// // 重置密码 -// secUser.setPassword(passwordEncoder.encode(Constant.DEF_PASSWORD)); -// } - secUserService.updateById(secUser); - return ApiResult.success(); - } - @ApiOperation("钉钉登录") - @RequestMapping(value = "/dingding", method = RequestMethod.GET) - public ApiResult login (@RequestParam("code") String requestAuthCode) throws Exception { - - - OapiUserGetuserinfoResponse response; - - String accessTokenRequest = DingTalkAccessTokenRequest.getAccessTokenRequest(); - String access_token = accessTokenRequest; - try { - - // - - // 获取用户信息 - DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo"); - OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest(); - request.setCode(requestAuthCode); - request.setHttpMethod("GET"); - - response = client.execute(request, access_token); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } - // 查询得到当前用户的userId - // 获得到userId之后应用应该处理应用自身的登录会话管理(session),避免后续的业务交互(前端到应用服务端)每次都要重新获取用户身份,提升用户体验 - String userId = response.getUserid(); - Map<String, Object> returnMap = new HashMap<String,Object>(); - returnMap.put("userId", userId); -// return ServiceResult.success(returnMap); - - - DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get"); - OapiV2UserGetRequest req = new OapiV2UserGetRequest(); - req.setUserid(userId); - OapiV2UserGetResponse rsp = client.execute(req, access_token); - System.out.println(rsp.getBody()); - - return ApiResult.success(); - } - @Autowired - private ALiSendSms aLiSendSms; -// @ApiOperation(value = "发送验证码", notes = "发送验证码") -// @PostMapping(value = "sendMsg") -// public ApiResult<String> sendMsg(@RequestBody VerificationCodeDTO dto) throws Exception { -// // 发送验证码并存储到redis -// if (StringUtils.hasLength(dto.getPhone())) { -// String code = String.valueOf((int) (Math.random() * 1000000)); -// redisAutoTemplate.setStr(dto.getPhone(), code); -// redisAutoTemplate.expire(dto.getPhone(), Constant.REDIS_EXPIRE); -// AliSms aliSms =new AliSms(); -// aliSms.setCode(code); -// aliSms.setProduct(dto.getPhone()); -// String json = JSONObject.toJSONString(aliSms); -// aLiSendSms.sendSms(dto.getPhone(), "SMS_58880127", json); -// return ApiResult.success("发送短信验证码成功!15分钟内有效"); -// } -// return ApiResult.failed(500, "发送短信验证码失败,请确认手机号码!"); -// } -- Gitblit v1.7.1