feat: 登录信息加密传输
This commit is contained in:
@@ -2,15 +2,22 @@ package tech.easyflow.admin.controller.auth;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import tech.easyflow.auth.entity.LoginDTO;
|
||||
import tech.easyflow.auth.entity.LoginVO;
|
||||
import tech.easyflow.auth.entity.*;
|
||||
import tech.easyflow.auth.service.AuthCredentialKeyService;
|
||||
import tech.easyflow.auth.service.AuthService;
|
||||
import tech.easyflow.common.captcha.tainai.CaptchaVerificationService;
|
||||
import tech.easyflow.common.constant.Constants;
|
||||
import tech.easyflow.common.domain.Result;
|
||||
import tech.easyflow.common.entity.LoginAccount;
|
||||
import tech.easyflow.common.satoken.util.SaTokenUtil;
|
||||
import tech.easyflow.common.web.exceptions.BusinessException;
|
||||
import tech.easyflow.common.web.jsonbody.JsonBody;
|
||||
import tech.easyflow.log.annotation.LogRecord;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
@@ -21,9 +28,23 @@ public class AuthController {
|
||||
|
||||
@Resource
|
||||
private AuthService authService;
|
||||
@Resource
|
||||
private AuthCredentialKeyService credentialKeyService;
|
||||
@Resource
|
||||
private CaptchaVerificationService captchaVerificationService;
|
||||
|
||||
@GetMapping("credential-key")
|
||||
public Result<CredentialKeyVO> credentialKey() {
|
||||
return Result.ok(credentialKeyService.getCurrentCredentialKey());
|
||||
}
|
||||
|
||||
@PostMapping("login")
|
||||
public Result<LoginVO> login(@JsonBody LoginDTO loginDTO) {
|
||||
public Result<LoginVO> login(@JsonBody EncryptedCredentialDTO encryptedCredential) {
|
||||
JSONObject payload = credentialKeyService.decryptPayload(encryptedCredential);
|
||||
if (!captchaVerificationService.verify(payload.getString("validToken"))) {
|
||||
return captchaVerificationService.failureResult();
|
||||
}
|
||||
LoginDTO loginDTO = toLoginDTO(payload);
|
||||
LoginVO res = authService.login(loginDTO);
|
||||
return Result.ok(res);
|
||||
}
|
||||
@@ -45,4 +66,23 @@ public class AuthController {
|
||||
List<String> permissionList = StpUtil.getPermissionList();
|
||||
return Result.ok(permissionList);
|
||||
}
|
||||
|
||||
@PostMapping("credential-key/rotate")
|
||||
@LogRecord("轮换认证传输密钥")
|
||||
public Result<Void> rotateCredentialKey(@JsonBody CredentialKeyRotateDTO rotateDTO) {
|
||||
StpUtil.checkLogin();
|
||||
LoginAccount loginAccount = SaTokenUtil.getLoginAccount();
|
||||
if (loginAccount == null || !Constants.SUPER_ADMIN_ID.equals(loginAccount.getId())) {
|
||||
throw new BusinessException("仅超级管理员可轮换认证密钥");
|
||||
}
|
||||
credentialKeyService.rotate(rotateDTO != null && Boolean.TRUE.equals(rotateDTO.getEmergency()));
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
private LoginDTO toLoginDTO(JSONObject payload) {
|
||||
LoginDTO loginDTO = new LoginDTO();
|
||||
loginDTO.setAccount(payload.getString("account"));
|
||||
loginDTO.setPassword(payload.getString("password"));
|
||||
return loginDTO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package tech.easyflow.admin.controller.system;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.crypto.digest.BCrypt;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
@@ -12,6 +13,8 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import tech.easyflow.auth.entity.EncryptedCredentialDTO;
|
||||
import tech.easyflow.auth.service.AuthCredentialKeyService;
|
||||
import tech.easyflow.common.constant.enums.EnumAccountType;
|
||||
import tech.easyflow.common.constant.enums.EnumDataStatus;
|
||||
import tech.easyflow.common.domain.Result;
|
||||
@@ -27,12 +30,13 @@ import tech.easyflow.system.entity.vo.SysAccountImportResultVo;
|
||||
import tech.easyflow.system.service.SysAccountService;
|
||||
import tech.easyflow.system.util.SysPasswordPolicy;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户表 控制层。
|
||||
@@ -43,8 +47,11 @@ import java.util.List;
|
||||
@RestController("sysAccountController")
|
||||
@RequestMapping("/api/v1/sysAccount")
|
||||
public class SysAccountController extends BaseCurdController<SysAccountService, SysAccount> {
|
||||
public SysAccountController(SysAccountService service) {
|
||||
private final AuthCredentialKeyService credentialKeyService;
|
||||
|
||||
public SysAccountController(SysAccountService service, AuthCredentialKeyService credentialKeyService) {
|
||||
super(service);
|
||||
this.credentialKeyService = credentialKeyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,7 +74,7 @@ public class SysAccountController extends BaseCurdController<SysAccountService,
|
||||
if (count > 0) {
|
||||
return Result.fail(1, "用户名已存在");
|
||||
}
|
||||
String password = entity.getPassword();
|
||||
String password = decryptInitialPassword(entity.getPasswordCredential());
|
||||
if (!StringUtil.hasText(password)) {
|
||||
return Result.fail(1, "密码不能为空");
|
||||
}
|
||||
@@ -143,14 +150,14 @@ public class SysAccountController extends BaseCurdController<SysAccountService,
|
||||
/**
|
||||
* 修改密码,用于修改用户自己的密码
|
||||
*
|
||||
* @param password 用户的旧密码
|
||||
* @param newPassword 新密码
|
||||
* @param confirmPassword 确认密码
|
||||
* @param encryptedCredential 加密后的旧密码、新密码与确认密码
|
||||
*/
|
||||
@PostMapping("/updatePassword")
|
||||
public Result<Void> updatePassword(@JsonBody(value = "password", required = true) String password,
|
||||
@JsonBody(value = "newPassword", required = true) String newPassword,
|
||||
@JsonBody(value = "confirmPassword", required = true) String confirmPassword) {
|
||||
public Result<Void> updatePassword(@JsonBody EncryptedCredentialDTO encryptedCredential) {
|
||||
JSONObject payload = credentialKeyService.decryptPayload(encryptedCredential);
|
||||
String password = payload.getString("password");
|
||||
String newPassword = payload.getString("newPassword");
|
||||
String confirmPassword = payload.getString("confirmPassword");
|
||||
BigInteger loginAccountId = SaTokenUtil.getLoginAccount().getId();
|
||||
SysAccount record = service.getById(loginAccountId);
|
||||
if (record == null) {
|
||||
@@ -174,6 +181,28 @@ public class SysAccountController extends BaseCurdController<SysAccountService,
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
private String decryptInitialPassword(Map<String, Object> passwordCredential) {
|
||||
if (passwordCredential == null || passwordCredential.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
JSONObject payload = credentialKeyService.decryptPayload(toEncryptedCredential(passwordCredential));
|
||||
return payload.getString("password");
|
||||
}
|
||||
|
||||
private EncryptedCredentialDTO toEncryptedCredential(Map<String, Object> passwordCredential) {
|
||||
EncryptedCredentialDTO encryptedCredential = new EncryptedCredentialDTO();
|
||||
encryptedCredential.setKeyId(asString(passwordCredential.get("keyId")));
|
||||
encryptedCredential.setEncryptedKey(asString(passwordCredential.get("encryptedKey")));
|
||||
encryptedCredential.setIv(asString(passwordCredential.get("iv")));
|
||||
encryptedCredential.setCiphertext(asString(passwordCredential.get("ciphertext")));
|
||||
encryptedCredential.setNonce(asString(passwordCredential.get("nonce")));
|
||||
return encryptedCredential;
|
||||
}
|
||||
|
||||
private String asString(Object value) {
|
||||
return value == null ? null : String.valueOf(value);
|
||||
}
|
||||
|
||||
@PostMapping("/resetPassword")
|
||||
@SaCheckPermission("/api/v1/sysAccount/save")
|
||||
public Result<Void> resetPassword(@JsonBody(value = "id", required = true) BigInteger id) {
|
||||
|
||||
Reference in New Issue
Block a user