From d1eadf7f5d015a3ab309f46c01e7ec54e1301c19 Mon Sep 17 00:00:00 2001 From: sh Date: Wed, 3 Jun 2026 12:33:46 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BC=98=E5=8C=96=E6=9F=A5=E8=AF=A2=E5=B2=97?= =?UTF-8?q?=E4=BD=8D=E8=AF=A6=E6=83=85=EF=BC=8C=E6=9F=A5=E8=AF=A2=E6=97=A0?= =?UTF-8?q?=E6=95=88=E5=B2=97=E4=BD=8D=E6=8F=90=E7=A4=BA=202.=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=BE=AE=E4=BF=A1=E6=8E=88=E6=9D=83=E7=99=BB=E5=BD=95?= =?UTF-8?q?=EF=BC=8C=E6=8A=8APKCS5Padding=20=E6=94=B9=E6=88=90PKCS7Padding?= =?UTF-8?q?=E5=B9=B6=E4=B8=94=E6=B7=BB=E5=8A=A0appid=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E4=B8=80=E8=87=B4=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cms/controller/app/AppJobController.java | 11 ++++--- .../cms/service/impl/JobServiceImpl.java | 9 +++--- .../java/com/ruoyi/cms/util/WechatUtil.java | 29 +++++++++++++++---- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/app/AppJobController.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/app/AppJobController.java index 362f6e7..c1fa801 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/app/AppJobController.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/app/AppJobController.java @@ -26,6 +26,7 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.List; +import java.util.Optional; /** * 岗位Controller @@ -172,18 +173,20 @@ public class AppJobController extends BaseController @GetMapping(value = "/{encryptJobId}") public AjaxResult getInfo(@PathVariable("encryptJobId") String encryptJobId, HttpServletRequest request) { + Long jobId; if(StringUtils.isBlank(encryptJobId)){ return error("岗位id为空!"); } try { - Long jobId=Long.parseLong(SM4Utils.decryptEcb(SM4Constants.SM4_KET, encryptJobId)); - //Job job = jobService.selectJobByJobIdApp(jobId); - Job job = jobService.selectHttpJobByJobIdApp(jobId,request); - return success(job); + String decryptStr=SM4Utils.decryptEcb(SM4Constants.SM4_KET, encryptJobId); + jobId=Long.parseLong(decryptStr); }catch (Exception e){ e.printStackTrace(); return error("参数不正确!"); } + return Optional.ofNullable(jobService.selectHttpJobByJobIdApp(jobId, request)) + .map(this::success) + .orElse(error("无效的岗位!")); } /** diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobServiceImpl.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobServiceImpl.java index 5eb9532..d204f9c 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobServiceImpl.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobServiceImpl.java @@ -617,11 +617,12 @@ public class JobServiceImpl extends ServiceImpl implements IJobSe @Override public Job selectHttpJobByJobIdApp(Long jobId,HttpServletRequest request) { Job job = jobMapper.selectById(jobId); - //查询公司信息 - if(Objects.nonNull(job.getCompanyId())){ - Company company = companyMapper.selectById(job.getCompanyId()); - job.setCompany(company); + if(job==null){ + return null; } + //查询公司信息 + Optional.ofNullable(job.getCompanyId()).map(companyMapper::selectById).ifPresent(job::setCompany); + if(SiteSecurityUtils.isLogin()){ //查询申请信息 Long applyCount = jobApplyMapper.selectCount(Wrappers.lambdaQuery().eq(JobApply::getJobId, jobId).eq(JobApply::getUserId, SiteSecurityUtils.getUserId())); diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/util/WechatUtil.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/util/WechatUtil.java index b8f8f17..128b6c9 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/util/WechatUtil.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/util/WechatUtil.java @@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; @@ -20,6 +21,7 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; +import java.security.Security; import java.util.Base64; import java.util.Formatter; import java.util.HashMap; @@ -41,6 +43,13 @@ public class WechatUtil { @Value("${wx.secret}") private String secret; + // 全局注册一次 BC Provider,避免每次解密都重复注册 + static { + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { + Security.addProvider(new BouncyCastleProvider()); + } + } + public AppWechatEntity sign(String url) { Map ret = new HashMap(); String nonceStr = create_nonce_str(); @@ -291,8 +300,8 @@ public class WechatUtil { throw new RuntimeException("iv长度错误,应为16字节"); } - // 2. 初始化 AES-128-CBC 解密器(使用PKCS5Padding替换PKCS7Padding,两者在AES中效果一致) - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + // 2. 初始化 AES-128-CBC 解密器 + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC"); SecretKeySpec keySpec = new SecretKeySpec(sessionKeyBytes, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); @@ -302,9 +311,19 @@ public class WechatUtil { String decryptedStr = new String(decryptedBytes, StandardCharsets.UTF_8); // 4. 解析为 JSON 并返回(包含手机号等信息) - return JSONObject.parseObject(decryptedStr); - } catch (Exception e) { - throw new RuntimeException("解密用户手机号失败:" + e.getMessage(), e); + JSONObject jsonObject=JSONObject.parseObject(decryptedStr); + // 5.验证 watermark 中的 appid 是否匹配,防止伪造数据攻击 + JSONObject watermark = jsonObject.getJSONObject("watermark"); + if (watermark == null || !appid.equals(watermark.getString("appid"))) { + throw new SecurityException("解密数据校验失败:appid不匹配,数据可能已被篡改!"); + } + + return jsonObject; + } catch (IllegalArgumentException | SecurityException e) { + throw new RuntimeException(e.getMessage(), e); + }catch (Exception e) { + System.err.println("微信手机号解密底层异常: " + e.getMessage()); + throw new RuntimeException("用户手机号解密失败,请检查登录态是否过期或参数是否正确"); } }