diff --git a/bonus-base/src/main/java/com/bonus/base/controller/system/SysLoginController.java b/bonus-base/src/main/java/com/bonus/base/controller/system/SysLoginController.java index be2b112..76cc6fd 100644 --- a/bonus-base/src/main/java/com/bonus/base/controller/system/SysLoginController.java +++ b/bonus-base/src/main/java/com/bonus/base/controller/system/SysLoginController.java @@ -3,6 +3,7 @@ package com.bonus.base.controller.system; import java.util.List; import java.util.Set; +import com.bonus.common.encryption.Sm4Utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -45,7 +46,6 @@ public class SysLoginController public AjaxResult sendPhone(@RequestBody String phone) { // 下发短信 AjaxResult ajax= loginService.sendPhone(phone); - return ajax; } @@ -58,17 +58,18 @@ public class SysLoginController */ @PostMapping("/login") public AjaxResult login(@RequestBody LoginBody loginBody) { + String token; AjaxResult ajax = AjaxResult.success(); if("2".equals(loginBody.getLoginType())){ + + token = loginService.login(loginBody.getUsername(), loginBody.getCode()); }else{ token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid()); } - // 生成令牌 - ajax.put(Constants.TOKEN, token); return ajax; } diff --git a/bonus-business/pom.xml b/bonus-business/pom.xml index 497182b..2118cf1 100644 --- a/bonus-business/pom.xml +++ b/bonus-business/pom.xml @@ -13,7 +13,17 @@ - + + + org.bytedeco + javacv + 1.5.10 + + + org.bytedeco + javacv-platform + 1.5.10 + com.bonus diff --git a/bonus-business/src/main/java/com/bonus/business/controller/VideoToMp4Converter.java b/bonus-business/src/main/java/com/bonus/business/controller/VideoToMp4Converter.java new file mode 100644 index 0000000..9aea8e4 --- /dev/null +++ b/bonus-business/src/main/java/com/bonus/business/controller/VideoToMp4Converter.java @@ -0,0 +1,61 @@ +package com.bonus.business.controller; + +import org.bytedeco.javacv.FFmpegFrameGrabber; +import org.bytedeco.javacv.FFmpegFrameRecorder; +import org.bytedeco.javacv.Frame; + +public class VideoToMp4Converter { + + /** + * 将视频文件转换为MP4格式 + * @param inputPath 输入视频文件路径 + * @param outputPath 输出MP4文件路径 + * @throws Exception 转换过程中的异常 + */ + public static void convertToMp4(String inputPath, String outputPath) throws Exception { + // 创建FFmpegFrameGrabber对象,读取输入视频 + FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath); + grabber.start(); + + // 创建FFmpegFrameRecorder对象,设置输出视频参数 + FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputPath, + grabber.getImageWidth(), + grabber.getImageHeight()); + + // 设置视频编码为H.264 + recorder.setVideoCodec(org.bytedeco.ffmpeg.global.avcodec.AV_CODEC_ID_H264); + // 设置输出格式为MP4 + recorder.setFormat("mp4"); + // 设置帧率与原视频保持一致 + recorder.setFrameRate(grabber.getFrameRate()); + // 设置音频通道数 + recorder.setAudioChannels(grabber.getAudioChannels()); + // 设置音频编码 + recorder.setAudioCodec(org.bytedeco.ffmpeg.global.avcodec.AV_CODEC_ID_AAC); + + recorder.start(); + + // 循环读取视频帧并进行录制 + Frame frame; + while ((frame = grabber.grabFrame()) != null) { + recorder.record(frame); + } + + // 关闭抓取器和录制器 + recorder.stop(); + grabber.stop(); + + System.out.println("视频转换完成!输出文件:" + outputPath); + } + + // 测试方法 + public static void main(String[] args) { + try { + String inputVideo = "input_video.flv"; // 输入视频文件,可以是任何格式 + String outputMp4 = "output_video.mp4"; // 输出MP4文件 + convertToMp4(inputVideo, outputMp4); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/bonus-business/src/main/java/com/bonus/business/mapper/ProductMapper.java b/bonus-business/src/main/java/com/bonus/business/mapper/ProductMapper.java index 1e1acb2..e9460dc 100644 --- a/bonus-business/src/main/java/com/bonus/business/mapper/ProductMapper.java +++ b/bonus-business/src/main/java/com/bonus/business/mapper/ProductMapper.java @@ -107,4 +107,11 @@ public interface ProductMapper { * @return */ int delProduct(TbProduct product); + + /** + * 判断名称是否存在 + * @param product + * @return + */ + Integer getProductByName(TbProduct product); } diff --git a/bonus-business/src/main/java/com/bonus/business/service/impl/ProductScreenImpl.java b/bonus-business/src/main/java/com/bonus/business/service/impl/ProductScreenImpl.java index b12211a..a75f3e5 100644 --- a/bonus-business/src/main/java/com/bonus/business/service/impl/ProductScreenImpl.java +++ b/bonus-business/src/main/java/com/bonus/business/service/impl/ProductScreenImpl.java @@ -56,10 +56,14 @@ public class ProductScreenImpl implements ProductScreenService { @Override public AjaxResult getProductDetails(TbProduct product) { try{ + //详情 TbProduct vo=mapper.getProductDetails(product); if(vo!=null){ + //封面图 + vo.setLinkImage(minioConfig.getUrl()+"/"+minioConfig.getBucketName()+vo.getLinkImage()); List productCases=productMapper.getProductCaseList(product.getId()); for (TbProductCase productCase:productCases) { + //产品案例 List caseImages=productMapper.getCaseImageByTable(productCase.getId(),"tb_product_case"); if(StringUtils.isNotEmpty(caseImages)){ caseImages.forEach(image->{ @@ -68,12 +72,14 @@ public class ProductScreenImpl implements ProductScreenService { productCase.setImageList(caseImages); } } + vo.setList(productCases); //查询 宣传手册和宣传视频 List list=mapper.getMaterialList(vo); List videoList=new ArrayList<>(); List fileList=new ArrayList<>(); if(StringUtils.isNotEmpty(list)){ list.forEach(vo1->{ + vo1.setImage(minioConfig.getUrl()+"/"+minioConfig.getBucketName()+vo1.getImage()); vo1.setUrl(minioConfig.getUrl()+"/"+minioConfig.getBucketName()+vo1.getFilePath()); if("0".equals(vo1.getFileType())){ videoList.add(vo1); @@ -85,9 +91,10 @@ public class ProductScreenImpl implements ProductScreenService { vo.setFileList(fileList); } } + return AjaxResult.success(vo); }catch (Exception e){ log.error(e.toString()); } - return null; + return AjaxResult.success(product); } } diff --git a/bonus-business/src/main/java/com/bonus/business/service/impl/ProductServiceImpl.java b/bonus-business/src/main/java/com/bonus/business/service/impl/ProductServiceImpl.java index 44c3ef3..3d2417f 100644 --- a/bonus-business/src/main/java/com/bonus/business/service/impl/ProductServiceImpl.java +++ b/bonus-business/src/main/java/com/bonus/business/service/impl/ProductServiceImpl.java @@ -98,6 +98,10 @@ public class ProductServiceImpl implements ProductService { product.setCreateUser(SecurityUtils.getUserId().toString()); product.setUpdateUser(SecurityUtils.getUserId().toString()); //新增产品及产品文件 + Integer isName=mapper.getProductByName(product); + if(isName!=null && isName>0){ + return AjaxResult.error("产品名称已存在"); + } int num=mapper.addProduct(product); List prFile=map.get("s"); AjaxResult ajaxResult1=uploadFile(prFile,"tb_product",product.getId(),"产品封面"); @@ -157,6 +161,10 @@ public class ProductServiceImpl implements ProductService { //修改产品 List proList=map.get("s"); product.setUpdateUser(SecurityUtils.getUserId().toString()); + Integer isName=mapper.getProductByName(product); + if(isName!=null && isName>0){ + return AjaxResult.error("产品名称已存在"); + } int isSuccess=mapper.updateProduct(product); //未跟新文件 if(StringUtils.isNotEmpty(proList)){ diff --git a/bonus-business/src/main/resources/mapper/business/ProductScreenMapper.xml b/bonus-business/src/main/resources/mapper/business/ProductScreenMapper.xml index 818a16f..20099b4 100644 --- a/bonus-business/src/main/resources/mapper/business/ProductScreenMapper.xml +++ b/bonus-business/src/main/resources/mapper/business/ProductScreenMapper.xml @@ -26,14 +26,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" where tpt.id=#{id} \ No newline at end of file diff --git a/bonus-business/src/main/resources/mapper/business/TbProductMapper.xml b/bonus-business/src/main/resources/mapper/business/TbProductMapper.xml index 7cdb22e..73a2bd0 100644 --- a/bonus-business/src/main/resources/mapper/business/TbProductMapper.xml +++ b/bonus-business/src/main/resources/mapper/business/TbProductMapper.xml @@ -59,6 +59,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from tb_product_case where product_id=#{id} and del_flag=0 + insert into tb_product @@ -120,7 +129,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" is_link = #{isLink}, introduction = #{introduction}, del_flag = #{delFlag}, - isAccess = #{isAccess}, + is_access = #{isAccess}, update_time =now(), update_user=#{updateUser} where id = #{id} diff --git a/bonus-common/pom.xml b/bonus-common/pom.xml index 2df71b3..a3bf8e8 100644 --- a/bonus-common/pom.xml +++ b/bonus-common/pom.xml @@ -16,6 +16,11 @@ + + org.bouncycastle + bcprov-jdk15on + 1.70 + cn.hutool hutool-all diff --git a/bonus-common/src/main/java/com/bonus/common/encryption/AesCbcUtils.java b/bonus-common/src/main/java/com/bonus/common/encryption/AesCbcUtils.java new file mode 100644 index 0000000..2429b9a --- /dev/null +++ b/bonus-common/src/main/java/com/bonus/common/encryption/AesCbcUtils.java @@ -0,0 +1,120 @@ +package com.bonus.common.encryption; + +import com.bonus.common.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.Security; + +/** + * AES加密工具类 + * + * @author HeiZi + */ +@Slf4j +public class AesCbcUtils { + //使用AES-256-CBC加密模式,key需要为16位,key和iv可以相同! + + /** + * 密钥算法 + */ + private static final String KEY_ALGORITHM = "AES"; + + /** + * 加密/解密算法 / 工作模式 / 填充方式 + * Java 6支持PKCS5Padding填充方式 + * Bouncy Castle支持PKCS7Padding填充方式 + */ + private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding"; + + /** + * 偏移量,只有CBC模式才需要 + */ + private final static String IV_PARAMETER = "1234567812345678"; + + + /** + * AES要求密钥长度为128位或192位或256位,java默认限制AES密钥长度最多128位 + */ + public static String sKey = "zhgd@bonus@zhgd@bonus@1234567890"; + + /** + * 编码格式导出 + */ + public static final String ENCODING = "utf-8"; + + static { + //如果是PKCS7Padding填充方式,则必须加上下面这行 + Security.addProvider(new BouncyCastleProvider()); + } + + /** + * AES加密 + * (CBC模式) + * + * @param source 源字符串 + * @param + * @return 加密后的密文 + * @throws Exception + */ + public static String encrypt(String source, String key, String encoding, String ivParameter, String cipherAlgorithm, String keyAlgorithm) { + try { + byte[] sourceBytes = source.getBytes(encoding); + byte[] keyBytes = key.getBytes(encoding); + Cipher cipher = Cipher.getInstance(cipherAlgorithm, "BC"); + IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(encoding)); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, keyAlgorithm), iv); + byte[] decrypted = cipher.doFinal(sourceBytes); + return Base64.encodeBase64String(decrypted); + } catch (Exception e) { + log.error(e.toString(), e); + } + return null; + } + +// public static void main(String[] args) { +// // String json=""; +// +// String json="{\"username\":\"guest\",\"password\":\"admin@123\"}"; +// String data=encrypt(json); +// System.err.println(data); +// String jm=decrypt("\"yeCxaGhmdDt+zDsKPr1prukR15BfIMLMOYIFKdgffGpMV76qVD8ANU4zsLiRZ87+7hd1Yje182nHhUOp/TeYCRuuUPQzmuXH7ikYVEWR1Rmc8uLq3G/BTMU6wFMSRFDBXARRl+dvnpyfX+MleF0KB1OAeuOIKv1gQPskmvDiFAniUlowf/96ZzMl7Bokqc/Lse8lMV92IQB14yQNa0+u/2kvdirzrcq+HCt9K8Ot3C59mjDqg49WoM65LEmaHmZqzdmmjbQlGH7ZOAFTLvF5kPzUsMz5Uim1uNvByB3eLFohc1UgB28DWoTyh43sRMPpq3S1BB20gcrBf3uVra/4qehBr3z98CGhGRyKHbjsCKl0Ri6YO1rp5aMRd9Y3wbOJFrZXFag5iifQx+ooDBeu6h1KCb5JfCjyAmw9+pgEL6X3eELPzK13XjblDyEikjx2Edv45MGsC0DUcjvz/Sb4E/8rn3o1Ep7W31xNCdn5mzZ8VO9POhE3DMK6woeN2C7TW+7YO/Zs9e4zKLS4vThvk5urCn2Ff2HkVBzoPtP2imuqQrY8898sbLllyaJEG0DPSrCf985ZgVa03JsO/EkMr3KAiHV5SHBZS1XEXqjdpL+YEdOnlfBXUk83kJhLj9rhUrTFza7ednQSzjq4XpIJJVy2aJhhj1chsmIM1Xl//0Dbak9Lb6VUq5Xr2IFAjNTgyxwtcFCdEvp4YZCSP6kqWgEpeAVlejyYOcNckUnWkjeHjtfgwvVsvUjWzyIRFCa7m/oY28xBV16RmW/r4XXquqKVdbPtATzrmf7pJCynXZ3IPd9ZGc1OTLnss9Ln9XNTH0E/I4Ma95fn9uxA+sOQkQ==\""); +// String jiemi=decrypt(data); +// System.err.println(jm); +// System.err.println(jiemi); +// } + + /** + * AES解密 + * (CBC模式) + * + * @param data 加密后的密文 + * @param + * @return 源字符串 + * @throws Exception + */ + public static String decrypt(String data, String key, String encoding, String ivParameter, String cipherAlgorithm, String keyAlgorithm) { + try { + String encryptStr = ""; + if (StringUtils.isNotEmpty(data)) { + encryptStr = data.replace(" ", "+"); + } + byte[] sourceBytes = Base64.decodeBase64(encryptStr); + byte[] keyBytes = key.getBytes(encoding); + Cipher cipher = Cipher.getInstance(cipherAlgorithm, "BC"); + IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(encoding)); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, keyAlgorithm), iv); + byte[] decoded = cipher.doFinal(sourceBytes); + return new String(decoded, encoding); + } catch (Exception e) { + log.info("------------------->请求加密参数不正确"); + log.error(e.toString(), e); + } + return null; + } + +} diff --git a/bonus-common/src/main/java/com/bonus/common/encryption/Sm2Util.java b/bonus-common/src/main/java/com/bonus/common/encryption/Sm2Util.java new file mode 100644 index 0000000..caee594 --- /dev/null +++ b/bonus-common/src/main/java/com/bonus/common/encryption/Sm2Util.java @@ -0,0 +1,68 @@ +package com.bonus.common.encryption; + +import cn.hutool.core.util.HexUtil; +import cn.hutool.crypto.BCUtil; +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.SM2; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; + + +/** + * @author 黑子 + * SM2加解密 + */ +public class Sm2Util { + + static SM2 sm2 = SmUtil.sm2(); + /** + * 获取公钥 + * @return + */ + public static String getPublicKey(){ + return HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false)); + } + + /** + * 获取私钥 + * @return + */ + public static String getPrivateKey(){ + return HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey())); + } + +// public static void main(String[] args) { +// String privateKey = getPrivateKey(); +// String publicKey = getPublicKey(); +// String msg= encrypt(publicKey,"1234567890"); +//// String msg2= decrypt(privateKey,msg); +// System.err.println(msg); +//// System.err.println(msg2); +// } + /** + * 加密 + *公钥加密 + * @param publicKey 公钥 + * @param data 明文 + * @return 密文 + */ + public static String encrypt(String publicKey, String data) { + return SmUtil.sm2(null, publicKey) + .encryptHex(data.getBytes(), KeyType.PublicKey) + // 加密后,密文前面会有04,需要去掉 + .substring(2); + } + /** + * 解密 + * 私钥解密 + * @param privateKey 私钥 + * @param data 密文 + * @return 明文 + */ + public static String decrypt(String privateKey, String data) { + // 前端加密是没有04的,所以解析的时候要加04 + data = "04" + data; + return SmUtil.sm2(privateKey, null) + .decryptStr(data, KeyType.PrivateKey); + } +} \ No newline at end of file diff --git a/bonus-common/src/main/java/com/bonus/common/encryption/Sm3Util.java b/bonus-common/src/main/java/com/bonus/common/encryption/Sm3Util.java new file mode 100644 index 0000000..4a129c0 --- /dev/null +++ b/bonus-common/src/main/java/com/bonus/common/encryption/Sm3Util.java @@ -0,0 +1,31 @@ +package com.bonus.common.encryption; + +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.digest.SM3; + +import java.io.File; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + + +/** + * @author weiweiw + * SM3加解密 + */ +public class Sm3Util { + + static SM3 sm3 = SmUtil.sm3WithSalt("2cc0c5f9f1749f1632efa9f63e902323".getBytes(StandardCharsets.UTF_8)); + + + public static String encrypt(String data) { + return Sm3Util.sm3.digestHex(data); + } + + public static String encrypt(InputStream data) { + return Sm3Util.sm3.digestHex(data); + } + + public static String encrypt(File dataFile) { + return Sm3Util.sm3.digestHex(dataFile); + } +} \ No newline at end of file diff --git a/bonus-common/src/main/java/com/bonus/common/encryption/Sm4Utils.java b/bonus-common/src/main/java/com/bonus/common/encryption/Sm4Utils.java new file mode 100644 index 0000000..b8e0107 --- /dev/null +++ b/bonus-common/src/main/java/com/bonus/common/encryption/Sm4Utils.java @@ -0,0 +1,67 @@ +package com.bonus.common.encryption; + +import cn.hutool.core.util.HexUtil; +import cn.hutool.crypto.Mode; +import cn.hutool.crypto.Padding; +import cn.hutool.crypto.symmetric.SM4; + +/** + * @author bonus + */ +public class Sm4Utils { + /** + * 必须是16字节 + */ + private static final String KEY = "78d1295afa99449b99d6f83820e6965c"; + + private static final String IV = "f555adf6c01d0ab0761e626a2dae34a2"; + /** + * 加密数据,使用固定盐 + * + * @param plainText 明文,待加密的字符串 + * @return 加密后的密文(包含盐),Hex 编码格式,如果加密异常就返回传入的字符串 + */ + public static String encrypt(String plainText) { + try { + SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, HexUtil.decodeHex(KEY),HexUtil.decodeHex(IV)); + // 加密带盐的明文 + byte[] encryptedData = sm4.encrypt(plainText); + // 返回带盐的加密结果(Hex编码) + return HexUtil.encodeHexStr(encryptedData); + } catch (Exception e) { + return plainText; // 发生异常时返回传入字符串 + } + } + + /** + * 解密数据,使用固定盐 + * + * @param cipherText 密文(包含盐),Hex 编码格式的字符串 + * @return 解密后的明文字符串,如果解密异常就返回传入的字符串 + */ + public static String decrypt(String cipherText) { + try { + // 初始化SM4解密工具 + SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, HexUtil.decodeHex(KEY),HexUtil.decodeHex(IV)); + // 解密数据 + byte[] decryptedData = sm4.decrypt(cipherText); + return new String(decryptedData); + } catch (Exception e) { + return cipherText; // 发生异常时返回传入字符串 + } + } + + // 测试方法,演示加密和解密过程 + public static void main(String[] args) { + String plainText = "15398187429"; + System.out.println("原文: " + plainText); + + // 加密明文 + String encryptedText = Sm4Utils.encrypt(plainText); + System.out.println("加密后: " + encryptedText); + + // 解密密文 + String decryptedText = Sm4Utils.decrypt(plainText); + System.out.println("解密后: " + decryptedText); + } +} diff --git a/bonus-framework/src/main/java/com/bonus/framework/web/service/SysLoginService.java b/bonus-framework/src/main/java/com/bonus/framework/web/service/SysLoginService.java index 44b2708..efe5da3 100644 --- a/bonus-framework/src/main/java/com/bonus/framework/web/service/SysLoginService.java +++ b/bonus-framework/src/main/java/com/bonus/framework/web/service/SysLoginService.java @@ -3,6 +3,7 @@ package com.bonus.framework.web.service; import javax.annotation.Resource; import com.bonus.common.core.domain.AjaxResult; +import com.bonus.common.encryption.Sm4Utils; import com.bonus.common.utils.PhoneUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; @@ -76,6 +77,8 @@ public class SysLoginService */ public String login(String username, String password, String code, String uuid) { + username= Sm4Utils.decrypt(username); + password= Sm4Utils.decrypt(password); // 验证码校验 validateCaptcha(username, code, uuid); // 登录前置校验 @@ -226,6 +229,7 @@ public class SysLoginService * @return */ public AjaxResult sendPhone(String phone) { + phone= Sm4Utils.decrypt(phone); //验证手机手机号是否存在 String thisUser=userService.getUserInfo(phone); if(!phone.equals(thisUser)){