| | |
| | | import org.springframework.security.crypto.password.PasswordEncoder; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import javax.annotation.Resource; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | |
| | | @Resource |
| | | private PasswordEncoder passwordEncoder; |
| | | |
| | | @Value("${app.captcha.required:true}") |
| | | private boolean captchaRequired; |
| | | |
| | | @PostMapping("/login") |
| | | public Result<Map<String, Object>> login(@RequestBody Map<String, Object> params) { |
| | | String username = (String) params.get("username"); |
| | |
| | | String captchaId = (String) params.get("captchaId"); |
| | | List<String> clickIds = strList(params.get("captchaClickIds")); |
| | | |
| | | CaptchaService.ConsumeResult cr = captchaService.consume(captchaId, clickIds); |
| | | if (cr == CaptchaService.ConsumeResult.NOT_FOUND) { |
| | | return Result.error(4002, "验证码不存在或已过期,请刷新重试"); |
| | | } |
| | | if (cr == CaptchaService.ConsumeResult.NOT_VERIFIED) { |
| | | return Result.error(4003, "请先完成行为验证"); |
| | | } |
| | | if (cr == CaptchaService.ConsumeResult.WRONG) { |
| | | return Result.error(4001, "行为验证未通过,请重新验证"); |
| | | if (captchaRequired) { |
| | | CaptchaService.ConsumeResult cr = captchaService.consume(captchaId, clickIds); |
| | | if (cr == CaptchaService.ConsumeResult.NOT_FOUND) { |
| | | return Result.error(4002, "验证码不存在或已过期,请刷新重试"); |
| | | } |
| | | if (cr == CaptchaService.ConsumeResult.NOT_VERIFIED) { |
| | | return Result.error(4003, "请先完成行为验证"); |
| | | } |
| | | if (cr == CaptchaService.ConsumeResult.WRONG) { |
| | | return Result.error(4001, "行为验证未通过,请重新验证"); |
| | | } |
| | | } |
| | | |
| | | if (username == null || username.trim().isEmpty() || password == null || password.isEmpty()) { |
| | |
| | | return Result.ok(data); |
| | | } |
| | | |
| | | /** 用户修改自己的密码:需提供原密码,新密码至少 6 位 */ |
| | | @PostMapping("/change-password") |
| | | public Result<Void> changePassword(@RequestHeader(value = "Authorization", required = false) String auth, |
| | | @RequestBody Map<String, Object> params) { |
| | | String username = jwtUtils.resolveUsername(auth); |
| | | if (username == null) { |
| | | return Result.error(401, "未登录或登录已过期"); |
| | | } |
| | | String oldPassword = (String) params.get("oldPassword"); |
| | | String newPassword = (String) params.get("newPassword"); |
| | | if (oldPassword == null || oldPassword.isEmpty()) { |
| | | return Result.error(400, "请输入原密码"); |
| | | } |
| | | if (newPassword == null || newPassword.length() < 6) { |
| | | return Result.error(400, "新密码长度不能少于 6 位"); |
| | | } |
| | | if (newPassword.equals(oldPassword)) { |
| | | return Result.error(400, "新密码不能与原密码相同"); |
| | | } |
| | | User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username)); |
| | | if (user == null) { |
| | | return Result.error(404, "用户不存在"); |
| | | } |
| | | String encoded = user.getPassword(); |
| | | boolean ok; |
| | | try { |
| | | ok = encoded != null && passwordEncoder.matches(oldPassword, encoded); |
| | | } catch (IllegalArgumentException e) { |
| | | // 库中密码不是合法 BCrypt 时回退为明文对比(与登录一致) |
| | | ok = encoded != null && encoded.equals(oldPassword); |
| | | } |
| | | if (!ok) { |
| | | return Result.error(400, "原密码错误"); |
| | | } |
| | | user.setPassword(passwordEncoder.encode(newPassword)); |
| | | userMapper.updateById(user); |
| | | return Result.ok(null); |
| | | } |
| | | |
| | | @GetMapping("/captcha-config") |
| | | public Result<Map<String, Object>> captchaConfig() { |
| | | Map<String, Object> data = new HashMap<>(); |
| | | data.put("required", captchaRequired); |
| | | return Result.ok(data); |
| | | } |
| | | |
| | | @SuppressWarnings("unchecked") |
| | | private List<String> strList(Object o) { |
| | | if (o instanceof List) { |