Commit 6232a738 by 刘红梅

刘红梅提交代码第一次

parent c0130482
...@@ -82,6 +82,31 @@ ...@@ -82,6 +82,31 @@
<version>32.0.1-android</version> <version>32.0.1-android</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>5.7.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.36</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.17.1</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.69</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package com.cnooc.expert.common.cache;
/**
* Redis Key管理
*
*/
public class RedisKeys {
private static final String CAPTCHA_KEY = "CAPTCHA_";
/**
* 验证码Key
*/
public static String getCaptchaKey(String key) {
// return "sys:captcha:" + key;
return CAPTCHA_KEY + key;
}
/**
* accessToken Key
*/
public static String getAccessTokenKey(String accessToken) {
return "sys:token:" + accessToken;
}
public static String getLogKey() {
return "sys:log";
}
}
package com.cnooc.expert.common.crypto;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* 采用国密SM3加密算法,对系统密码进行加密
*
*/
public class Sm3PasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return SmUtil.sm3(rawPassword.toString());
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return StrUtil.equals(SmUtil.sm3(rawPassword.toString()), encodedPassword);
}
}
package com.cnooc.expert.common.utils;
import com.cnooc.expert.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
/**
* @author lyh
* 2016年10月24日 上午9:34:32
*/
@Slf4j
public class AesUtil {
private static final String KEY_TYPE = "AES";
private static final String CIPHER_TYPE = "AES/ECB/PKCS5Padding";
/**
* 加密
*
* @param content
* 要加密的内容
* @param password
* 密码
* @return 加密后的字符串
*/
public static String encrypt(String content, String password) {
String realKey = AesUtil.md5Encode(password);
SecretKeySpec sks = new SecretKeySpec(AesUtil.hex2byte(realKey),
KEY_TYPE);
byte[] cipherByte = null;
try {
Cipher c1 = Cipher.getInstance(CIPHER_TYPE);
c1.init(Cipher.ENCRYPT_MODE, sks);
cipherByte = c1.doFinal(content.getBytes("UTF-8"));
// 返回密文的十六进制形式
return byte2hex(cipherByte);
} catch (Exception e) {
log.error("e:{}", e);
throw new BusinessException("加密失败");
}
}
/**
* 解密
*
* @param content
* 要解密的内容
* @param password
* 密码
* @return 解密结果
*/
public static String decrypt(String content, String password) {
String realKey = AesUtil.md5Encode(password);
SecretKeySpec sks = new SecretKeySpec(AesUtil.hex2byte(realKey),
KEY_TYPE);
byte[] cipherByte = null;
try {
Cipher c1 = Cipher.getInstance(CIPHER_TYPE);
c1.init(Cipher.DECRYPT_MODE, sks);
cipherByte = c1.doFinal(hex2byte(content));
return new String(cipherByte);
} catch (Exception e) {
log.error("e:{}", e);
throw new BusinessException("解密失败");
}
}
/**
* 生成MD5摘要
*/
public static String md5Encode(String info) {
try {
MessageDigest alga = MessageDigest.getInstance("MD5");
alga.update(info.getBytes("UTF-8"));
return byte2hex(alga.digest());
} catch (Exception e) {
return null;
}
}
/**
* 将二进制转化为16进制字符串
*/
public static String byte2hex(byte[] b) {
StringBuilder bder = new StringBuilder();
String stmp = null;
for (int n = 0; n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0XFF);
if (stmp.length() == 1) {
bder.append("0");
}
bder.append(stmp);
}
return bder.toString().toUpperCase();
}
/**
* 十六进制字符串转化为byte数组
*/
private static byte[] hex2byte(String hex) {
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("参数长度不合法");
}
byte[] result = new byte[hex.length() / 2];
for (int i = 0; i < result.length; i++) {
result[i] = uniteBytes(hex.charAt(i * 2), hex.charAt(i * 2 + 1));
}
return result;
}
/**
* 将两个ASCII字符合成一个字节; 如:"EF"--> 0xEF
*
* @param c1
* @param c2
* @return byte
*/
private static byte uniteBytes(char c1, char c2) {
byte _b0 = Byte.decode("0x" + c1);
_b0 = (byte) (_b0 << 4);
byte _b1 = Byte.decode("0x" + c2);
return (byte) (_b0 ^ _b1);
}
}
package com.cnooc.expert.common.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
/**
* 公用的工具类
* @author zhengkai
*
* @date 2015年5月25日 上午11:34:35
*/
public class CommonUtil {
public static final Long SO_FAR_TINE = new Long(-1L);
/**
* 时间转换成字符串(采用 yyyy-MM-dd HH:mm:ss)
* @param longtime
* @return
* @author zhengkai
* @date 2015年5月9日 下午2:43:28F
*/
public static String longTimeToString(Long longtime){
if (SO_FAR_TINE.equals(longtime)) {
return "至今";
}
if(longtime!=null){
Date dt=(new Date(longtime));
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(dt);
}
return "";
}
public static String LongTimeToStringOnDay(Long longtime){
if (SO_FAR_TINE.equals(longtime)) {
return "至今";
}
if(longtime!=null){
Date dt=(new Date(longtime));
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(dt);
}
return "";
}
/**
* 时间转换成字符串
* @param longtime
* @param formatter
* @return
* @author zhengkai
* @date 2015年5月9日 下午2:43:28
*/
public static String LongTimeToString(Long longtime,String formatter){
if (SO_FAR_TINE.equals(longtime)) {
return "至今";
}
if(longtime!=null){
Date dt=(new Date(longtime));
SimpleDateFormat sdf=new SimpleDateFormat(formatter);
return sdf.format(dt);
}
return "";
}
/**
* 字符串值是否相同
* <p>
* 注意:只比较视觉值 即null = '' = ' '
* </p>
*
* @param str1
* @param str2
* @return
*/
public static boolean stringValSame(String str1, String str2){
str1 = Objects.toString(str1, "").trim();
str2 = Objects.toString(str2, "").trim();
return str1.equals(str2);
}
/**
* 二开 - Boolean类型转成字符串展示
*
* @param val
* @return true->是;false->否
*/
public static String convertBool2Str(Boolean val){
if (Objects.isNull(val)) {
return "";
}
return Boolean.TRUE.equals(val) ? "是" : "否";
}
}
package com.cnooc.expert.common.utils;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.util.ArrayList;
import java.util.List;
/**
* JSON 工具类
*
*/
public class JsonUtils {
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.registerModule(new JavaTimeModule());
// objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public static String toJsonString(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> T parseObject(String text, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
return null;
}
try {
return objectMapper.readValue(text, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
if (ArrayUtil.isEmpty(bytes)) {
return null;
}
try {
return objectMapper.readValue(bytes, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> T parseObject(String text, TypeReference<T> typeReference) {
try {
return objectMapper.readValue(text, typeReference);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> List<T> parseArray(String text, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
return new ArrayList<>();
}
try {
return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package com.cnooc.expert.common.utils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
public class RestUtils {
private static final RestTemplate restTemplate = new RestTemplate();
/**
* 发送 Base64 编码的 JSON POST 请求
*
* @param apiUrl API 地址
* @param requestBody 请求体 Map
* @return 响应字符串
*/
public static <T> T sendPostRequest(String apiUrl, Map<String, String> headersMap,
String requestBody, ParameterizedTypeReference<T> responseType) {
try {
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if(!CollectionUtils.isEmpty(headersMap)) {
headersMap.forEach(headers::set);
}
// 构建请求实体
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<T> response = restTemplate.exchange(apiUrl, HttpMethod.POST, requestEntity, responseType);
return response.getBody();
} catch (Exception e) {
throw new RuntimeException("发送 POST 请求失败", e);
}
}
public static <T> T sendPostRequest2Expert(String relativeUrl, String requestBody, ParameterizedTypeReference<T> responseType){
String fullUrl = "http://10.xxx.xxx.xxx"+relativeUrl;
Map<String, String> headers = new HashMap<>();
headers.put("Access-Key", "Ysy9ht");
return sendPostRequest(fullUrl, headers, requestBody, responseType);
}
}
package com.cnooc.expert.common.utils;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.util.encoders.Hex;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* 国密SM2加密算法
*
*/
public class Sm2Util {
/**
* 公钥
*/
private final static String PUBLIC_KEY = "3059301306072a8648ce3d020106082a811ccf5501822d034200040a302b5e4b961afb3908a4ae191266ac5866be100fc52e3b8dba9707c8620e64ae790ceffc3bfbf262dc098d293dd3e303356cb91b54861c767997799d2f0060";
/**
* 私钥
*/
private final static String PRIVATE_KEY = "308193020100301306072a8648ce3d020106082a811ccf5501822d047930770201010420d7840173df3d6cd72cad4040dfc7dbfcde539f5b490b54f3cd5c4125544b38aea00a06082a811ccf5501822da144034200040a302b5e4b961afb3908a4ae191266ac5866be100fc52e3b8dba9707c8620e64ae790ceffc3bfbf262dc098d293dd3e303356cb91b54861c767997799d2f0060";
private final static SM2 sm2;
static {
sm2 = SmUtil.sm2(PRIVATE_KEY, PUBLIC_KEY);
}
/**
* 加密
*
* @param data 明文
* @return 加密后的密文
*/
public static String encrypt(String data) {
return sm2.encryptBase64(data, KeyType.PublicKey);
}
/**
* 解密
*
* @param data 加密后的密文
* @return 解密后的明文
*/
public static String decrypt(String data) {
return sm2.decryptStr(data, KeyType.PrivateKey);
}
public static void main(String[] args) {
KeyPair keyPair = SecureUtil.generateKeyPair("SM2");
System.out.println("privateKey:" + HexUtil.encodeHexStr(keyPair.getPrivate().getEncoded()));
System.out.println("publicKey:" + HexUtil.encodeHexStr(keyPair.getPublic().getEncoded()));
PublicKey publicKey = keyPair.getPublic();
if (publicKey instanceof BCECPublicKey) {
// 获取65字节非压缩缩的十六进制公钥串(0x04)
String publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));
System.out.println("SM2公钥:" + publicKeyHex);
}
PrivateKey privateKey = keyPair.getPrivate();
if (privateKey instanceof BCECPrivateKey) {
// 获取32字节十六进制私钥串
String privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
System.out.println("SM2私钥:" + privateKeyHex);
}
String password = "admin";
String sm2Password = Sm2Util.encrypt(password);
System.out.println("sm2 加密:" + sm2Password);
System.out.println("sm2 解密:" + Sm2Util.decrypt(sm2Password));
System.out.println("sm3 解密:" + SmUtil.sm3("admin"));
}
}
package com.cnooc.expert.common.utils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
public class SmsHttpUtil {
private static final RestTemplate restTemplate = new RestTemplate();
/**
* 发送 Base64 编码的 JSON POST 请求
*
* @param apiUrl API 地址
* @param requestBody 请求体 Map
* @return 响应字符串
*/
public static String sendPostRequest(String apiUrl, String requestBody) {
try {
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 构建请求实体
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
return restTemplate.postForObject(apiUrl, requestEntity, String.class);
} catch (Exception e) {
throw new RuntimeException("发送 POST 请求失败", e);
}
}
}
package com.cnooc.expert.common.utils;
import cn.hutool.core.util.RandomUtil;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.Map;
@Slf4j
public class SmsUtil {
/**
* 生成6位随机验证码
*/
public static String generateVerificationCode() {
return RandomUtil.randomNumbers(6);
}
/**
* 构建 Redis 缓存键
*/
public static String buildCacheKey(String phone) {
return "sms:code:" + phone;
}
/**
* 构建短信内容
*/
public static String buildSmsContent(String code) {
return "福建通信行业融合创新服务平台,您的验证码是:" + code + "(有效期为2分钟),请勿泄露给他人,如非本人操作,请忽略此消息。";
}
/**
* 将请求体转换为 Base64 编码的 JSON 字符串
*/
public static String encodeRequestBodyToBase64(Map<String, String> requestBody) {
String jsonString = JsonUtils.toJsonString(requestBody);
return Base64.getEncoder().encodeToString(jsonString.getBytes(StandardCharsets.UTF_8));
}
/**
* 处理响应结果
*/
public static boolean handleResponse(String response) throws Exception {
JsonNode jsonNode = JsonUtils.parseObject(response, JsonNode.class);
if (jsonNode.get("success").asBoolean()) {
System.out.println("云MAS业务平台短信验证码发送成功");
log.info("云MAS业务平台短信验证码发送成功");
return true;
} else {
System.out.println("云MAS业务平台短信验证码发送失败");
log.info("云MAS业务平台短信验证码发送失败");
return false;
}
}
public static String calculateMac(String ecName, String apld, String secretKey, String mobiles, String content, String sign, String addSerial) {
try{
// 根据文档中的规则计算MAC
StringBuilder sb = new StringBuilder();
sb.append(ecName).append(apld).append(secretKey).append(mobiles).append(content).append(sign).append(addSerial);
return DigestUtils.md5Hex(sb.toString());
} catch (Exception e) {
throw new RuntimeException("生成MAC签名失败", e);
}
}
public static String generateMD5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (Exception e) {
throw new RuntimeException("生成MAC签名失败", e);
}
}
}
package com.cnooc.expert.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.cnooc.expert.common.crypto.Sm3PasswordEncoder;
/**
* 加密配置
*
*/
@Configuration
public class PasswordConfig {
@Bean
public PasswordEncoder passwordEncoder() {
// 使用国密SM3加密
return new Sm3PasswordEncoder();
}
}
package com.cnooc.expert.system.entity.vo;
import lombok.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
/**
* 接收登录的form表单数据
* @Author: FuHongZhang
* @CreateTime: 2025-09-18 15:11
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginVO {
private String phoneNumber;
private String phoneCode;
private String idNumber;
private String password;
@Max(value = 2, message = "登录类型只能是1,手机验证码登录 2.身份证密码登录")
@Min(value = 1)
private Integer loginType;
//图形验证码的key
private String key;
//图片验证码
private String captcha;
}
package com.cnooc.expert.system.entity.vo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "sms.config")
public class SmsConfig {
private String apiUrl;
private String ecName;
private String apId;
private String secretKey;
private String sign;
private String addSerial;
}
package com.cnooc.expert.system.entity.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class SysCaptchaVO implements Serializable {
private static final long serialVersionUID = 1L;
private String key;
//image base64
private String image;
}
\ No newline at end of file
package com.cnooc.expert.system.entity.vo;
import lombok.Data;
import java.io.Serializable;
/**
* @author: FuHongZhang
* @date 2025-10-22 17:03
*/
@Data
public class VerifyCodeVO implements Serializable {
private String phoneNumber;
private String phoneCode;
}
package com.cnooc.expert.system.entity.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class ZhuanJiaInfoAppVo implements Serializable {
private static final long serialVersionUID = 1L;
private String baseGuid;
private String password;
}
package com.cnooc.expert.system.entity.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class ZhuanJiaInfoVo implements Serializable {
private String baseGuid;
private String mobile;
private String shengfenzheng;
private String password;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment