LoginController.java 12 KB

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