LoginController.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. package com.xjrsoft.module.system.controller;
  2. import cn.dev33.satoken.annotation.SaCheckPermission;
  3. import cn.dev33.satoken.session.SaSession;
  4. import cn.dev33.satoken.stp.StpUtil;
  5. import cn.hutool.core.util.IdUtil;
  6. import cn.hutool.core.util.StrUtil;
  7. import cn.hutool.extra.spring.SpringUtil;
  8. import cn.hutool.jwt.JWT;
  9. import cn.hutool.jwt.JWTUtil;
  10. import com.baomidou.mybatisplus.core.toolkit.StringPool;
  11. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  12. import com.xjrsoft.common.annotation.XjrLog;
  13. import com.xjrsoft.common.constant.GlobalConstant;
  14. import com.xjrsoft.common.model.result.R;
  15. import com.xjrsoft.common.model.result.RT;
  16. import com.xjrsoft.common.sms.SmsCtcc;
  17. import com.xjrsoft.common.utils.QrCodeUtil;
  18. import com.xjrsoft.common.utils.RedisUtil;
  19. import com.xjrsoft.config.CommonPropertiesConfig;
  20. import com.xjrsoft.config.KeyCloakConfig;
  21. import com.xjrsoft.module.organization.entity.User;
  22. import com.xjrsoft.module.organization.service.IUserService;
  23. import com.xjrsoft.module.student.dto.QRLoginDto;
  24. import com.xjrsoft.module.system.dto.CaptchaDto;
  25. import com.xjrsoft.module.system.dto.CreateAuthorizeUrlDto;
  26. import com.xjrsoft.module.system.dto.CreateTokenDto;
  27. import com.xjrsoft.module.system.dto.KeyCloakLoginInfoDto;
  28. import com.xjrsoft.module.system.dto.LoginByCodeDto;
  29. import com.xjrsoft.module.system.dto.LoginCaptchaDto;
  30. import com.xjrsoft.module.system.dto.LoginDto;
  31. import com.xjrsoft.module.system.dto.LoginQRCodeDto;
  32. import com.xjrsoft.module.system.service.ILoginService;
  33. import com.xjrsoft.module.system.service.IOauthService;
  34. import com.xjrsoft.module.system.vo.LoginCheckQRCodeVo;
  35. import com.xjrsoft.module.system.vo.LoginQRCodeVo;
  36. import io.swagger.annotations.Api;
  37. import io.swagger.annotations.ApiOperation;
  38. import lombok.AllArgsConstructor;
  39. import me.zhyd.oauth.request.AuthRequest;
  40. import me.zhyd.oauth.utils.AuthStateUtils;
  41. import org.apache.commons.lang3.RandomUtils;
  42. import org.keycloak.authorization.client.AuthzClient;
  43. import org.keycloak.authorization.client.Configuration;
  44. import org.keycloak.representations.AccessTokenResponse;
  45. import org.springframework.web.bind.annotation.GetMapping;
  46. import org.springframework.web.bind.annotation.PostMapping;
  47. import org.springframework.web.bind.annotation.RequestBody;
  48. import org.springframework.web.bind.annotation.RequestMapping;
  49. import org.springframework.web.bind.annotation.RequestParam;
  50. import org.springframework.web.bind.annotation.RestController;
  51. import javax.validation.Valid;
  52. import java.util.HashMap;
  53. import java.util.Map;
  54. /**
  55. * <p>
  56. * 登录控制器
  57. * </p>
  58. *
  59. * @author tzx
  60. * @since 2022-03-02
  61. */
  62. @Api(tags = "登录模块")
  63. @RestController
  64. @RequestMapping(GlobalConstant.SYSTEM_MODULE_PREFIX)
  65. @AllArgsConstructor
  66. public class LoginController {
  67. private final ILoginService loginService;
  68. private final IUserService userService;
  69. private final RedisUtil redisUtil;
  70. private KeyCloakConfig keyCloakConfig;
  71. private final SmsCtcc smsCtcc;
  72. private IOauthService oauthService;
  73. private final CommonPropertiesConfig commonPropertiesConfig;
  74. @PostMapping("/login")
  75. @ApiOperation(value = "登录", notes = "传入账号:account,密码:password")
  76. @XjrLog(value = "账号密码登录成功")
  77. public R login(@RequestBody @Valid LoginDto dto) throws Exception {
  78. return R.ok(loginService.login(dto));
  79. }
  80. @PostMapping("/findUserByCode")
  81. @ApiOperation(value = "登录", notes = "code")
  82. @XjrLog(value = "Code登录成功")
  83. public R findUserByCode(@RequestBody @Valid LoginByCodeDto dto) throws Exception {
  84. return R.ok(loginService.findUserByCode(dto));
  85. }
  86. @PostMapping("/loginByCode")
  87. @ApiOperation(value = "登录", notes = "code")
  88. @XjrLog(value = "Code登录成功")
  89. public R loginByCode(@RequestBody @Valid LoginByCodeDto dto) throws Exception {
  90. return R.ok(loginService.loginByCode(dto));
  91. }
  92. @GetMapping(value = "/loginQRCode")
  93. @ApiOperation(value="登录-二维码")
  94. @SaCheckPermission("login:detail")
  95. public RT<LoginQRCodeVo> qrcode() {
  96. long loginCode = IdUtil.getSnowflakeNextId();
  97. String url = commonPropertiesConfig.getDomainApp() + "pages/login/qrCodeLogin/index?loginCode="+loginCode;
  98. String active = SpringUtil.getActiveProfile();
  99. if(!"prod".equals(active)){
  100. url = "http://yxh-web.ngrok.yingcaibx.com/app/#/pages/login/qrCodeLogin/index?loginCode="+loginCode;
  101. }
  102. int width = 200;
  103. int height = 200;
  104. int margin = 1;
  105. try {
  106. String base64 = QrCodeUtil.createBase64(url, width, height, margin);
  107. LoginQRCodeVo loginQRCodeVo = new LoginQRCodeVo();
  108. loginQRCodeVo.setImgBase64(base64);
  109. redisUtil.set(loginCode + "time", System.currentTimeMillis());
  110. loginQRCodeVo.setLoginCode(loginCode + "");
  111. return RT.ok(loginQRCodeVo);
  112. } catch (Exception e) {
  113. return RT.error(e.getMessage());
  114. }
  115. }
  116. @PostMapping("/QR-code-login")
  117. @ApiOperation(value = "二维码登录", notes = "code")
  118. @XjrLog(value = "二维码登录")
  119. public RT<String> loginQRCode(@RequestBody LoginQRCodeDto dto) throws Exception {
  120. // Long timestamp = redisUtil.get(dto.getLoginCode() + "time", Long.class);
  121. // long timeMillis = System.currentTimeMillis();
  122. // if(timeMillis - timestamp > 300000){
  123. // return RT.error("二维码失效,请刷新重试");
  124. // }
  125. Boolean b = loginService.loginQRCode(dto);
  126. if(b){
  127. return RT.ok("登录成功");
  128. }
  129. return RT.ok("登录失败,未能绑定微信公众号");
  130. }
  131. @PostMapping("/check-QR-code-login")
  132. @ApiOperation(value = "验证是否登录成功", notes = "验证是否登录成功")
  133. @XjrLog(value = "验证是否登录成功")
  134. public RT<LoginCheckQRCodeVo> checkLoginQRCode(@RequestBody @Valid QRLoginDto dto) {
  135. Long timestamp = redisUtil.get(dto.getLoginCode() + "time", Long.class);
  136. if(timestamp == null){
  137. timestamp = System.currentTimeMillis();
  138. }
  139. long timeMillis = System.currentTimeMillis();
  140. LoginCheckQRCodeVo loginCheckQRCodeVo = new LoginCheckQRCodeVo();
  141. if(timeMillis - timestamp > 300000){
  142. loginCheckQRCodeVo.setStatus(1);
  143. return RT.ok(loginCheckQRCodeVo);
  144. }
  145. String token = redisUtil.get(dto.getLoginCode());
  146. loginCheckQRCodeVo.setToken(token);
  147. loginCheckQRCodeVo.setStatus(0);
  148. return RT.ok(loginCheckQRCodeVo);
  149. }
  150. @PostMapping("/bindOpenid")
  151. @ApiOperation(value = "登录", notes = "登录")
  152. @XjrLog(value = "code换Openid并绑定")
  153. public R bindOpenid(@RequestBody @Valid LoginByCodeDto dto) throws Exception {
  154. return R.ok(loginService.bindOpenid(dto));
  155. }
  156. @GetMapping("/imgcaptcha")
  157. @ApiOperation(value = "图形验证码", notes = "图形验证码")
  158. public R imgCaptcha() {
  159. return R.ok(loginService.imgCaptcha());
  160. }
  161. @PostMapping("/create-token")
  162. @ApiOperation(value = "创建token", notes = "传入账号:account,密码:password")
  163. @XjrLog(value = "账号密码登录成功")
  164. public R createToken(@RequestBody @Valid CreateTokenDto dto) {
  165. return R.ok(loginService.createToken(dto));
  166. }
  167. /**
  168. * 发送验证码
  169. */
  170. @PostMapping("/captcha")
  171. @XjrLog(value = "发送验证码")
  172. @ApiOperation(value = "发送验证码", notes = "传入账号:mobile")
  173. public R captcha(@RequestBody @Valid CaptchaDto captchaDto) {
  174. String active = SpringUtil.getActiveProfile();
  175. String code = "111111";
  176. // 测试环境使用模拟短信,正式环境才发送短信
  177. if (active.equals("prod")) {
  178. // String captchaCode = redisUtil.get(captchaDto.getKey(), 0);
  179. // if (captchaCode == null) {
  180. // throw new MyException("验证码已过期,请刷新验证码!");
  181. // }
  182. //
  183. // if (!captchaCode.equals(captchaDto.getCode())) {
  184. // throw new MyException("验证码不正确,请刷新验证码!");
  185. // }
  186. //生成六位数的字符串
  187. code = RandomUtils.nextInt(100000, 999999) + StringPool.EMPTY;
  188. smsCtcc.sendCaptcha(captchaDto.getMobile(), code, true);
  189. } else {
  190. smsCtcc.sendCaptcha(captchaDto.getMobile(), code, false);
  191. }
  192. return R.ok(Boolean.TRUE);
  193. }
  194. /**
  195. * 验证码登录
  196. */
  197. @PostMapping("/loginCaptcha")
  198. @XjrLog(value = "验证码登录")
  199. public R loginByCaptcha(@RequestBody LoginCaptchaDto loginCaptchaDto) throws Exception {
  200. // 验证验证码
  201. if (!smsCtcc.captchaVerify(loginCaptchaDto.getMobile(), loginCaptchaDto.getCode())) {
  202. return R.error("验证码不正确!");
  203. }
  204. return R.ok(loginService.loginByCaptcha(loginCaptchaDto));
  205. }
  206. /**
  207. * 退出
  208. */
  209. @PostMapping("/logout")
  210. public R logout() {
  211. StpUtil.logout();
  212. return R.ok("登出成功!");
  213. }
  214. @PostMapping("/token")
  215. @ApiOperation(value = "根据keycloak-token 登录", notes = "传入keycloak-token")
  216. @XjrLog(value = "keycloak-token登录成功")
  217. public R loginByToken(@RequestBody KeyCloakLoginInfoDto dto) {
  218. Map<String, Object> credentialsMap = new HashMap<>(1);
  219. credentialsMap.put("secret", keyCloakConfig.getSecret());
  220. Configuration configuration = new Configuration(keyCloakConfig.getUrl(), keyCloakConfig.getRealm(), keyCloakConfig.getClientId(), credentialsMap, null);
  221. AuthzClient authzClient = AuthzClient.create(configuration);
  222. AccessTokenResponse response = authzClient.obtainAccessToken(keyCloakConfig.getUserName(), keyCloakConfig.getPassword());
  223. if (StrUtil.isNotBlank(response.getError())) {
  224. return R.error(response.getError());
  225. }
  226. //TODO keycloak 登陆过 解析token获取数据 做框架登录操作
  227. JWT jwt = JWTUtil.parseToken(dto.getToken());
  228. Object code = jwt.getPayload(keyCloakConfig.getPayload());
  229. User user = userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getCode, code));
  230. if (user == null) {
  231. return R.error("帐号密码错误!");
  232. } else if (!Integer.valueOf(1).equals(user.getEnabledMark())) {
  233. return R.error("该账号已被禁用!");
  234. }
  235. //此登录接口登录web端
  236. StpUtil.login(user.getId(), dto.getDevice());
  237. SaSession tokenSession = StpUtil.getTokenSession();
  238. tokenSession.set(GlobalConstant.LOGIN_USER_INFO_KEY, user);
  239. Map<String, Object> vo = new HashMap<>(1);
  240. vo.put(GlobalConstant.TOKEN_KEY, StpUtil.getTokenValue());
  241. return R.ok("登录成功!", vo);
  242. }
  243. @PostMapping("/qrcode-login")
  244. @ApiOperation(value = "oauth 扫码登录", notes = "oauth 扫码登录")
  245. @XjrLog(value = "oauth 扫码登录")
  246. public R createAuthorizeUrl(@Valid @RequestBody CreateAuthorizeUrlDto dto){
  247. AuthRequest authRequest = oauthService.getAuthRequest(dto.getSource());
  248. String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
  249. return R.ok(authorizeUrl);
  250. }
  251. }