4 changed files with 165 additions and 217 deletions
@ -1,4 +1,113 @@ |
|||||
package com.zdxt.enforcementcode.controller.app; |
package com.zdxt.enforcementcode.controller.app; |
||||
|
|
||||
public class LoginController { |
import cn.dev33.satoken.stp.StpUtil; |
||||
|
import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
||||
|
import cn.hutool.crypto.digest.DigestUtil; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.dromara.common.core.domain.R; |
||||
|
import org.dromara.common.core.domain.model.LoginUser; |
||||
|
import org.dromara.common.satoken.utils.LoginHelper; |
||||
|
|
||||
|
import javax.crypto.Cipher; |
||||
|
import javax.crypto.spec.IvParameterSpec; |
||||
|
import javax.crypto.spec.SecretKeySpec; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.util.Base64; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* App端登录公共基类 |
||||
|
* 提供AES解密、参数校验、密码校验、SaToken登录等公共方法 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
public abstract class LoginController { |
||||
|
|
||||
|
/** |
||||
|
* AES密钥(与前端一致) |
||||
|
*/ |
||||
|
protected static final String AES_KEY = "1234567898745621"; |
||||
|
|
||||
|
/** |
||||
|
* 校验登录参数非空 |
||||
|
* |
||||
|
* @return 校验失败返回错误R,校验通过返回null |
||||
|
*/ |
||||
|
protected R<Map<String, Object>> validateLoginParams(String secretName, String secretKey) { |
||||
|
if (secretName == null || secretName.isBlank()) { |
||||
|
return R.fail("用户名不能为空"); |
||||
|
} |
||||
|
if (secretKey == null || secretKey.isBlank()) { |
||||
|
return R.fail("密码不能为空"); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* AES解密前端传来的密码 |
||||
|
* |
||||
|
* @return 解密后的明文密码,失败返回null |
||||
|
*/ |
||||
|
protected String decryptPassword(String secretKey) { |
||||
|
try { |
||||
|
return decryptByAes(secretKey); |
||||
|
} catch (Exception e) { |
||||
|
log.error("密码解密失败", e); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* MD5加盐校验密码: MD5(loginName + password + salt) |
||||
|
*/ |
||||
|
protected boolean verifyPassword(String loginName, String decryptedPassword, String salt, String storedPassword) { |
||||
|
String md5Password = DigestUtil.md5Hex(loginName + decryptedPassword + salt); |
||||
|
return md5Password.equals(storedPassword); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 构建LoginUser并执行SaToken登录 |
||||
|
* |
||||
|
* @return SaToken令牌值 |
||||
|
*/ |
||||
|
protected String doSaTokenLogin(Long userId, String userName, String nickName, String deptId, |
||||
|
String userType, String deviceType, String clientId) { |
||||
|
LoginUser loginUser = new LoginUser(); |
||||
|
loginUser.setUserId(userId); |
||||
|
loginUser.setUsername(userName); |
||||
|
loginUser.setNickname(nickName); |
||||
|
loginUser.setUserType(userType); |
||||
|
loginUser.setDeptId(deptId); |
||||
|
|
||||
|
SaLoginParameter model = new SaLoginParameter(); |
||||
|
model.setDeviceType(deviceType); |
||||
|
model.setExtra("clientid", clientId); |
||||
|
LoginHelper.login(loginUser, model); |
||||
|
|
||||
|
return StpUtil.getTokenValue(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* AES/CBC/ZeroPadding 解密(与前端CryptoJS对应) |
||||
|
* 前端使用 CryptoJS.pad.ZeroPadding,Java中用NoPadding后手动去除尾部0字节 |
||||
|
*/ |
||||
|
private String decryptByAes(String encryptedBase64) throws Exception { |
||||
|
byte[] keyBytes = AES_KEY.getBytes(StandardCharsets.UTF_8); |
||||
|
byte[] ivBytes = AES_KEY.getBytes(StandardCharsets.UTF_8); |
||||
|
|
||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); |
||||
|
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); |
||||
|
|
||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); |
||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); |
||||
|
|
||||
|
byte[] encrypted = Base64.getDecoder().decode(encryptedBase64); |
||||
|
byte[] decrypted = cipher.doFinal(encrypted); |
||||
|
|
||||
|
// 去除ZeroPadding尾部的0字节
|
||||
|
int len = decrypted.length; |
||||
|
while (len > 0 && decrypted[len - 1] == 0) { |
||||
|
len--; |
||||
|
} |
||||
|
return new String(decrypted, 0, len, StandardCharsets.UTF_8); |
||||
|
} |
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue