Browse Source

代码重构

dev-V1.0.1
庄锐波 7 months ago
parent
commit
e2e9c743ea
  1. 111
      ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/LoginController.java
  2. 91
      ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java
  3. 89
      ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enterprise/AppEntLoginController.java
  4. 91
      ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/supervision/AppSupLoginController.java

111
ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/LoginController.java

@ -1,4 +1,113 @@
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);
}
}

91
ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java

@ -1,14 +1,10 @@
package com.zdxt.enforcementcode.controller.app.enforcement;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.crypto.digest.DigestUtil;
import com.zdxt.enforcementcode.controller.app.LoginController;
import lombok.RequiredArgsConstructor;
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 org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysDeptService;
@ -18,11 +14,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
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.HashMap;
import java.util.Map;
@ -33,16 +24,11 @@ import java.util.Map;
@RequiredArgsConstructor
@RestController
@RequestMapping("/app-enf/login")
public class AppEnfLoginController {
public class AppEnfLoginController extends LoginController {
private final ISysUserService sysUserService;
private final ISysDeptService sysDeptService;
/**
* AES密钥(与前端一致)
*/
private static final String AES_KEY = "1234567898745621";
/**
* 执法端用户登录
*
@ -55,40 +41,35 @@ public class AppEnfLoginController {
String secretName = params.get("secretName");
String secretKey = params.get("secretKey");
if (secretName == null || secretName.isBlank()) {
return R.fail("用户名不能为空");
}
if (secretKey == null || secretKey.isBlank()) {
return R.fail("密码不能为空");
// 1. 参数校验
R<Map<String, Object>> paramCheck = validateLoginParams(secretName, secretKey);
if (paramCheck != null) {
return paramCheck;
}
// 1. 根据用户名查询 sys_user 表
// 2. 根据用户名查询 sys_user 表
SysUserVo user = sysUserService.selectUserByUserName(secretName);
if (user == null) {
return R.fail("用户不存在");
}
// 2. 检查用户状态(0正常 1停用)
// 3. 检查用户状态(0正常 1停用)
if ("1".equals(user.getStatus())) {
return R.fail("该用户已被停用");
}
// 3. AES解密前端传来的密码
String decryptedPassword;
try {
decryptedPassword = decryptByAes(secretKey);
} catch (Exception e) {
log.error("密码解密失败", e);
// 4. AES解密前端传来的密码
String decryptedPassword = decryptPassword(secretKey);
if (decryptedPassword == null) {
return R.fail("密码解密失败");
}
// 4. MD5加盐校验密码: MD5(username + password + salt)
String md5Password = DigestUtil.md5Hex(user.getUserName() + decryptedPassword + user.getSalt());
if (!md5Password.equals(user.getPassword())) {
// 5. MD5加盐校验密码
if (!verifyPassword(user.getUserName(), decryptedPassword, user.getSalt(), user.getPassword())) {
return R.fail("用户名或密码错误");
}
// 5. 查询部门信息
// 6. 查询部门信息
String deptName = "";
if (user.getDeptId() != null && !user.getDeptId().isBlank()) {
SysDeptVo dept = sysDeptService.selectDeptById(user.getDeptId());
@ -97,22 +78,13 @@ public class AppEnfLoginController {
}
}
// 6. 构建LoginUser并生成SaToken
LoginUser loginUser = new LoginUser();
loginUser.setUserId(user.getUserId());
loginUser.setUsername(user.getUserName());
loginUser.setNickname(user.getNickName());
loginUser.setUserType("enforcement_user");
loginUser.setDeptId(user.getDeptId());
// 7. 构建LoginUser并生成SaToken
String token = doSaTokenLogin(user.getUserId(), user.getUserName(), user.getNickName(),
user.getDeptId(), "enforcement_user", "enforcement_app", "enforcement");
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType("enforcement_app");
model.setExtra("clientid", "enforcement");
LoginHelper.login(loginUser, model);
// 7. 构造返回数据
// 8. 构造返回数据
Map<String, Object> data = new HashMap<>();
data.put("token", StpUtil.getTokenValue());
data.put("token", token);
data.put("userId", user.getUserId());
data.put("userName", user.getUserName());
data.put("nickName", user.getNickName());
@ -122,29 +94,4 @@ public class AppEnfLoginController {
return R.ok(data);
}
/**
* 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);
}
}

89
ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enterprise/AppEntLoginController.java

@ -1,24 +1,15 @@
package com.zdxt.enforcementcode.controller.app.enterprise;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.crypto.digest.DigestUtil;
import com.zdxt.enforcementcode.controller.app.LoginController;
import com.zdxt.enforcementcode.domain.vo.EnterpriseUserVo;
import com.zdxt.enforcementcode.service.IEnterpriseInformationService;
import com.zdxt.enforcementcode.service.IEnterpriseUserService;
import lombok.RequiredArgsConstructor;
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 org.springframework.web.bind.annotation.*;
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.HashMap;
import java.util.Map;
@ -29,16 +20,11 @@ import java.util.Map;
@RequiredArgsConstructor
@RestController
@RequestMapping("/app-ent/login")
public class AppEntLoginController {
public class AppEntLoginController extends LoginController {
private final IEnterpriseUserService enterpriseUserService;
private final IEnterpriseInformationService enterpriseInformationService;
/**
* AES密钥(与前端一致)
*/
private static final String AES_KEY = "1234567898745621";
/**
* 企业端用户登录
*
@ -51,57 +37,41 @@ public class AppEntLoginController {
String secretName = params.get("secretName");
String secretKey = params.get("secretKey");
if (secretName == null || secretName.isBlank()) {
return R.fail("用户名不能为空");
}
if (secretKey == null || secretKey.isBlank()) {
return R.fail("密码不能为空");
// 1. 参数校验
R<Map<String, Object>> paramCheck = validateLoginParams(secretName, secretKey);
if (paramCheck != null) {
return paramCheck;
}
// 1. 根据登录名查询用户
// 2. 根据登录名查询用户
EnterpriseUserVo user = enterpriseUserService.queryByLoginName(secretName);
if (user == null) {
return R.fail("用户不存在");
}
// 2. 检查用户状态
// 3. 检查用户状态
if ("1".equals(user.getStatus())) {
return R.fail("该用户已被停用");
}
// 3. AES解密前端传来的密码
String decryptedPassword;
try {
decryptedPassword = decryptByAes(secretKey);
} catch (Exception e) {
log.error("密码解密失败", e);
// 4. AES解密前端传来的密码
String decryptedPassword = decryptPassword(secretKey);
if (decryptedPassword == null) {
return R.fail("密码解密失败");
}
// 4. MD5加盐校验密码: MD5(username + password + salt)
String md5Password = DigestUtil.md5Hex(user.getLoginName() + decryptedPassword + user.getSalt());
if (!md5Password.equals(user.getPassword())) {
// 5. MD5加盐校验密码
if (!verifyPassword(user.getLoginName(), decryptedPassword, user.getSalt(), user.getPassword())) {
return R.fail("用户名或密码错误");
}
// 5. 构建LoginUser并生成SaToken
LoginUser loginUser = new LoginUser();
loginUser.setUserId(user.getUserId());
loginUser.setUsername(user.getUserName());
loginUser.setNickname(user.getNickName());
loginUser.setUserType("enterprise_user");
loginUser.setDeptId(user.getDeptId());
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType("enterprise_app");
model.setExtra("clientid", "enterprise");
LoginHelper.login(loginUser, model);
// 6. 构建LoginUser并生成SaToken
String token = doSaTokenLogin(user.getUserId(), user.getUserName(), user.getNickName(),
user.getDeptId(), "enterprise_user", "enterprise_app", "enterprise");
// 7. 构造返回数据
Map<String, Object> data = new HashMap<>();
data.put("token", StpUtil.getTokenValue());
data.put("token", token);
data.put("userId", user.getUserId());
data.put("userName", user.getUserName());
data.put("nickName", user.getNickName());
@ -109,29 +79,4 @@ public class AppEntLoginController {
return R.ok(data);
}
/**
* 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);
}
}

91
ruoyi-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/supervision/AppSupLoginController.java

@ -1,14 +1,10 @@
package com.zdxt.enforcementcode.controller.app.supervision;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.crypto.digest.DigestUtil;
import com.zdxt.enforcementcode.controller.app.LoginController;
import lombok.RequiredArgsConstructor;
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 org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysDeptService;
@ -18,11 +14,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
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.HashMap;
import java.util.Map;
@ -33,16 +24,11 @@ import java.util.Map;
@RequiredArgsConstructor
@RestController
@RequestMapping("/app-sup/login")
public class AppSupLoginController {
public class AppSupLoginController extends LoginController {
private final ISysUserService sysUserService;
private final ISysDeptService sysDeptService;
/**
* AES密钥(与前端一致)
*/
private static final String AES_KEY = "1234567898745621";
/**
* 监督端用户登录
*
@ -55,40 +41,35 @@ public class AppSupLoginController {
String secretName = params.get("secretName");
String secretKey = params.get("secretKey");
if (secretName == null || secretName.isBlank()) {
return R.fail("用户名不能为空");
}
if (secretKey == null || secretKey.isBlank()) {
return R.fail("密码不能为空");
// 1. 参数校验
R<Map<String, Object>> paramCheck = validateLoginParams(secretName, secretKey);
if (paramCheck != null) {
return paramCheck;
}
// 1. 根据用户名查询 sys_user 表
// 2. 根据用户名查询 sys_user 表
SysUserVo user = sysUserService.selectUserByUserName(secretName);
if (user == null) {
return R.fail("用户不存在");
}
// 2. 检查用户状态(0正常 1停用)
// 3. 检查用户状态(0正常 1停用)
if ("1".equals(user.getStatus())) {
return R.fail("该用户已被停用");
}
// 3. AES解密前端传来的密码
String decryptedPassword;
try {
decryptedPassword = decryptByAes(secretKey);
} catch (Exception e) {
log.error("密码解密失败", e);
// 4. AES解密前端传来的密码
String decryptedPassword = decryptPassword(secretKey);
if (decryptedPassword == null) {
return R.fail("密码解密失败");
}
// 4. MD5加盐校验密码: MD5(username + password + salt)
String md5Password = DigestUtil.md5Hex(user.getUserName() + decryptedPassword + user.getSalt());
if (!md5Password.equals(user.getPassword())) {
// 5. MD5加盐校验密码
if (!verifyPassword(user.getUserName(), decryptedPassword, user.getSalt(), user.getPassword())) {
return R.fail("用户名或密码错误");
}
// 5. 查询部门信息
// 6. 查询部门信息
String deptName = "";
if (user.getDeptId() != null && !user.getDeptId().isBlank()) {
SysDeptVo dept = sysDeptService.selectDeptById(user.getDeptId());
@ -97,22 +78,13 @@ public class AppSupLoginController {
}
}
// 6. 构建LoginUser并生成SaToken
LoginUser loginUser = new LoginUser();
loginUser.setUserId(user.getUserId());
loginUser.setUsername(user.getUserName());
loginUser.setNickname(user.getNickName());
loginUser.setUserType("supervision_user");
loginUser.setDeptId(user.getDeptId());
// 7. 构建LoginUser并生成SaToken
String token = doSaTokenLogin(user.getUserId(), user.getUserName(), user.getNickName(),
user.getDeptId(), "supervision_user", "supervision_app", "supervision");
SaLoginParameter model = new SaLoginParameter();
model.setDeviceType("supervision_app");
model.setExtra("clientid", "supervision");
LoginHelper.login(loginUser, model);
// 7. 构造返回数据
// 8. 构造返回数据
Map<String, Object> data = new HashMap<>();
data.put("token", StpUtil.getTokenValue());
data.put("token", token);
data.put("userId", user.getUserId());
data.put("userName", user.getUserName());
data.put("nickName", user.getNickName());
@ -122,29 +94,4 @@ public class AppSupLoginController {
return R.ok(data);
}
/**
* 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…
Cancel
Save