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.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; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; 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 java.util.HashMap; import java.util.Map; import java.util.Objects; /** *

* 会员表 前端控制器 *

* * @author xiaochen * @since 2021-07-28 */ @Slf4j @Api(tags = "用户登录相关") @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; @Autowired private PasswordEncoder passwordEncoder; @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; } // @ApiOperation(value = "通过code获得openid") // @GetMapping("openId-by-jscode2session/{code}") // public ApiResult> 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 tokenInfos = securityUtils.login(null, null, authenticationManager, SecUser.class, 3); // return ApiResult.success(tokenInfos); // } // @ApiOperation(value = "账号与小程序进行绑定") // @GetMapping("openidBindPhone/{code}/{account}") // public ApiResult 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> 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 token = securityUtils.login(username, password, authenticationManager, SecurityUserDetails.class, 2); // return ApiResult.success(token); // } catch (Exception e) { // e.printStackTrace(); // ApiResult> 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> login1(@Validated @RequestBody LoginDTO loginDto) { //验证是否通过验证 // if (ObjectUtils.isEmpty(loginDto.getVerify()) || !loginDto.getVerify()) { // ApiResult> 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 token = securityUtils.login(username, password, authenticationManager, SecurityUserDetails.class, 1); return ApiResult.success(token); } catch (Exception e) { ApiResult> failed = ApiResult.failed(new HashMap<>(1)); failed.setCode(0); failed.setSuccess(false); failed.setMsg(e.getMessage()); return failed; } } /** * 登录接口 */ // @OperLoginLog // @ApiOperation("选择用户账号登录") // @PostMapping(value = "choose-login") // public ApiResult> 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 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> 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> 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 list = secUserService.list(Wrappers.lambdaQuery(SecUser.class) //// .eq(SecUser::getPhone, phone)); //// list = list.stream().filter(o -> !o.getShortName().contains("admin")).collect(Collectors.toList()); //// Map token = securityUtils.login(phone, code, authenticationManager, SecurityUserDetails.class, true); // //保存登录记录 // return ApiResult.success(new ArrayList<>()); // } catch (Exception e) { // ApiResult> failed = ApiResult.failed(new ArrayList<>(1)); // failed.setCode(0); // failed.setSuccess(false); // failed.setMsg(e.getMessage()); // return failed; // } // } @ApiOperation("发送验证码") @PostMapping(value = "sendCode") public ApiResult 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 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> 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 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> failed = ApiResult.failed(new HashMap<>(1)); failed.setCode(0); failed.setSuccess(false); failed.setMsg(e.getMessage()); return failed; } } @ApiOperation("退出登录") @GetMapping("logout") public ApiResult logout() { boolean flag = securityUtils.invalidateToken(WebUtils.request()); if (flag) { return ApiResult.success("退出成功"); } return ApiResult.success(); } @OperationLog(operType = "修改", operDesc = "密码修改", operModul = "用户") @ApiOperation("首页密码修改") @PostMapping("/pageResetPassword") public ApiResult 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 returnMap = new HashMap(); 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 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, "发送短信验证码失败,请确认手机号码!"); // } }