diff --git a/src/main/java/com/chinaweal/aiccs/org/controller/TUsersappController.java b/src/main/java/com/chinaweal/aiccs/org/controller/TUsersappController.java new file mode 100644 index 0000000..ad28eec --- /dev/null +++ b/src/main/java/com/chinaweal/aiccs/org/controller/TUsersappController.java @@ -0,0 +1,221 @@ +package com.chinaweal.aiccs.org.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.chinaweal.aiccs.common.util.RSAUTil; +import com.chinaweal.aiccs.common.util.StringUtils; +import com.chinaweal.aiccs.org.entity.TUsersapp; +import com.chinaweal.aiccs.org.service.TUsersappService; +import com.chinaweal.aiccs.redis.RedisService; +import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException; +import com.chinaweal.youfool.framework.springboot.rest.RestResult; +import com.chinaweal.youfool.framework.sso.util.SSOUtil; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Base64; + +/** + * 用户APP信息管理 + */ +@Api(tags = "用户APP信息管理") +@ApiSupport(author = "system") +@RestController +@RequestMapping("/usersapp") +@Slf4j +public class TUsersappController { + + @Autowired + private TUsersappService tUsersappService; + + @Resource + private RedisService redisService; + + @Value("${redis-usersapp-privatekey.expire:300}") + private int privateKeyExpire; + + private static final String REDIS_PRIVATE_KEY_PREFIX = "usersapp:rsa:privatekey:"; + + private static final String RSA_COOKIE_KEY = "usersapprsa"; + + /** + * 接口1:检查用户对应的TUsersapp中有没有身份证号和手机号码的记录 + * + * @param request 请求 + * @return true-有完整记录,false-没有完整记录 + */ + @GetMapping("/check") + @ApiOperation(value = "检查用户是否有身份证号和手机号码记录") + public RestResult checkUserInfo(HttpServletRequest request) { + String userId = SSOUtil.getUser().getPrimaryKey(); + if (StringUtils.isBlank(userId)) { + return RestResult.error(com.chinaweal.youfool.framework.springboot.rest.ResultCode.USER_NOT_LOGGED_IN); + } + TUsersapp byId = tUsersappService.getById(userId); + + return RestResult.ok(byId != null && StringUtils.isNotBlank(byId.getMobile()) && StringUtils.isNotBlank(byId.getIdentityno())); + } + + /** + * 接口2:获取RSA密钥对 + * 公钥返回给前端,私钥存储在Redis中 + * Redis的key后缀使用cookie中的值 + * + * @param request 请求 + * @return 公钥 + */ + @GetMapping("/getPublicKey") + @ApiOperation(value = "获取RSA公钥") + public RestResult getRsaPublicKey(HttpServletRequest request, HttpServletResponse response) { + String cookieValue = getCookieValue(request, RSA_COOKIE_KEY); + if (StringUtils.isBlank(cookieValue)) { + cookieValue = StringUtils.getUUID(); + setCookieValue(response, RSA_COOKIE_KEY, cookieValue); + } + + try { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + keyPairGen.initialize(1024, new java.security.SecureRandom()); + KeyPair keyPair = keyPairGen.generateKeyPair(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + + String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded()); + String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded()); + + // 私钥存储到Redis,key后缀使用cookie值 + String redisKey = REDIS_PRIVATE_KEY_PREFIX + cookieValue; + redisService.set(redisKey, privateKeyString, privateKeyExpire); + + return RestResult.ok(publicKeyString); + } catch (NoSuchAlgorithmException e) { + log.error("生成RSA密钥对失败", e); + throw new BusinessException("生成RSA密钥对失败"); + } + } + + /** + * 接口3:用户账号信息设置接口 + * 用户传入身份证号(RSA密文)、手机号(RSA密文) + * 将证件号和手机号解密后,查询TUsersapp表,确保数据是唯一的 + * 如果不唯一,则抛出BusinessException说明信息已被占用 + * 否则创建或更新TUsersapp的记录 + * + * @param identityNoEncrypted 身份证号密文 + * @param mobileEncrypted 手机号密文 + * @param request 请求 + * @return 设置结果 + */ + @PostMapping("/setUserInfo") + @ApiOperation(value = "设置用户账号信息") + public RestResult setUserInfo( + @ApiParam("身份证号密文") @RequestParam String identityNoEncrypted, + @ApiParam("手机号密文") @RequestParam String mobileEncrypted, + HttpServletRequest request) { + String userId = SSOUtil.getUser().getPrimaryKey(); + if (StringUtils.isEmpty(userId)) { + return RestResult.error(com.chinaweal.youfool.framework.springboot.rest.ResultCode.USER_NOT_LOGGED_IN); + } + + String cookieValue = getCookieValue(request, RSA_COOKIE_KEY); + if (StringUtils.isEmpty(cookieValue)) { + throw new BusinessException("Cookie不存在或已过期"); + } + + // 从Redis获取私钥 + String redisKey = REDIS_PRIVATE_KEY_PREFIX + cookieValue; + String privateKeyString = redisService.get(redisKey); + if (StringUtils.isEmpty(privateKeyString)) { + throw new BusinessException("传输加密的密钥已过期,请刷新页面重新获取"); + } + + try { + // 解密身份证号和手机号 + String identityNo = RSAUTil.decrypt(identityNoEncrypted, privateKeyString); + String mobile = RSAUTil.decrypt(mobileEncrypted, privateKeyString); + + // 查询是否存在相同的身份证号或手机号(排除当前用户) + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.and(w -> w + .eq(TUsersapp::getIdentityno, identityNo) + .or() + .eq(TUsersapp::getMobile, mobile) + ).ne(TUsersapp::getUserid, userId); + + long count = tUsersappService.count(wrapper); + if (count > 0) { + throw new BusinessException("身份证号或手机号已被其他用户占用"); + } + + // 查询当前用户的TUsersapp记录 + TUsersapp existUser = tUsersappService.getById(userId); + + if (existUser != null) { + // 更新记录 + existUser.setIdentityno(identityNo); + existUser.setMobile(mobile); + tUsersappService.updateById(existUser); + } else { + // 创建新记录 + TUsersapp newUser = new TUsersapp(); + newUser.setUserid(userId); + newUser.setIdentityno(identityNo); + newUser.setMobile(mobile); + tUsersappService.save(newUser); + } + + // 删除Redis中的私钥 + redisService.remove(redisKey); + + return RestResult.ok(); + } catch (BusinessException e) { + throw e; + } catch (Exception e) { + log.error("设置用户账号信息失败", e); + throw new BusinessException("解密失败或处理异常"); + } + } + + /** + * 获取Cookie中的值 + */ + private String getCookieValue(HttpServletRequest request, String cookieKey) { + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + // 根据实际情况修改cookie名称 + if (cookieKey.equals(cookie.getName())) { + return cookie.getValue(); + } + } + } + return null; + } + + /** + * 设置cookie + * + * @param response response + * @param cookieKey cookieKey + * @param cookieValue cookie值 + */ + private void setCookieValue(HttpServletResponse response, String cookieKey, String cookieValue) { + Cookie cookie = new Cookie(cookieKey, cookieValue); + cookie.setPath("/aiccs-api"); + response.addCookie(cookie); + } +} diff --git a/src/main/java/com/chinaweal/aiccs/org/entity/TUsersapp.java b/src/main/java/com/chinaweal/aiccs/org/entity/TUsersapp.java new file mode 100644 index 0000000..5eabe64 --- /dev/null +++ b/src/main/java/com/chinaweal/aiccs/org/entity/TUsersapp.java @@ -0,0 +1,125 @@ +package com.chinaweal.aiccs.org.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDate; + +/** + *

+ * 用户补充信息 + *

+ * + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "T_USERSAPP", schema = "CXAICORG") +public class TUsersapp extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 用户id + */ + @TableId(value = "USERID") + @ApiModelProperty("用户id") + private String userid; + + /** + * 性别 + */ + @TableField("GENDER") + @ApiModelProperty("性别") + private String gender; + + /** + * 联系电话号码 + */ + @ApiModelProperty("联系电话号码") + @TableField("PHONENUMBER") + private String phonenumber; + + /** + * 手机号 + */ + @ApiModelProperty("手机号") + @TableField("MOBILE") + private String mobile; + + /** + * 邮箱 + */ + @ApiModelProperty("邮箱") + @TableField("EMAIL") + private String email; + + /** + * 地址 + */ + @ApiModelProperty("地址") + @TableField("ADDRESS") + private String address; + + /** + * 工号 + */ + @ApiModelProperty("工号") + @TableField("WORKNO") + private String workno; + + /** + * 工作类型 + */ + @ApiModelProperty("工作类型") + @TableField("WORKTYPE") + private String worktype; + + /** + * 生日日期 + */ + @ApiModelProperty("生日日期") + @TableField("BIRTHDAY") + private LocalDate birthday; + + /** + * 雇用日期 + */ + @ApiModelProperty("雇用日期") + @TableField("HIREDATE") + private LocalDate hiredate; + + /** + * 离职日期 + */ + @ApiModelProperty("离职日期") + @TableField("LEAVEDATE") + private LocalDate leavedate; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + @TableField("IDENTITYNO") + private String identityno; + + /** + * 备注 + */ + @ApiModelProperty("备注") + @TableField("REMARK") + private String remark; + + @Override + protected Serializable pkVal() { + return this.userid; + } + +} diff --git a/src/main/java/com/chinaweal/aiccs/org/mapper/TUsersappMapper.java b/src/main/java/com/chinaweal/aiccs/org/mapper/TUsersappMapper.java new file mode 100644 index 0000000..e907a6b --- /dev/null +++ b/src/main/java/com/chinaweal/aiccs/org/mapper/TUsersappMapper.java @@ -0,0 +1,14 @@ +package com.chinaweal.aiccs.org.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chinaweal.aiccs.org.entity.TUsersapp; + +/** + *

+ * Mapper 接口 + *

+ * + */ +public interface TUsersappMapper extends BaseMapper { + +} diff --git a/src/main/java/com/chinaweal/aiccs/org/service/TUsersappService.java b/src/main/java/com/chinaweal/aiccs/org/service/TUsersappService.java new file mode 100644 index 0000000..c02ccb7 --- /dev/null +++ b/src/main/java/com/chinaweal/aiccs/org/service/TUsersappService.java @@ -0,0 +1,14 @@ +package com.chinaweal.aiccs.org.service; + +import com.chinaweal.aiccs.org.entity.TUsersapp; +import com.chinaweal.youfool.framework.springboot.mybatis.plus.BaseService; + +/** + *

+ * 服务类 + *

+ * + */ +public interface TUsersappService extends BaseService { + +} diff --git a/src/main/java/com/chinaweal/aiccs/org/service/impl/TUsersappServiceImpl.java b/src/main/java/com/chinaweal/aiccs/org/service/impl/TUsersappServiceImpl.java new file mode 100644 index 0000000..a16fafb --- /dev/null +++ b/src/main/java/com/chinaweal/aiccs/org/service/impl/TUsersappServiceImpl.java @@ -0,0 +1,18 @@ +package com.chinaweal.aiccs.org.service.impl; + +import com.chinaweal.aiccs.org.entity.TUsersapp; +import com.chinaweal.aiccs.org.mapper.TUsersappMapper; +import com.chinaweal.aiccs.org.service.TUsersappService; +import com.chinaweal.youfool.framework.springboot.mybatis.plus.BaseServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + */ +@Service +public class TUsersappServiceImpl extends BaseServiceImpl implements TUsersappService { + +} diff --git a/src/main/resources/mybatis/mapper/aicorg/org/TUsersappMapper.xml b/src/main/resources/mybatis/mapper/aicorg/org/TUsersappMapper.xml new file mode 100644 index 0000000..91059d8 --- /dev/null +++ b/src/main/resources/mybatis/mapper/aicorg/org/TUsersappMapper.xml @@ -0,0 +1,5 @@ + + + + +