提交 28b1915a 编写于 作者: Chongwen.jiang's avatar Chongwen.jiang

Merge branch 'dev-login0218' of...

Merge branch 'dev-login0218' of 192.168.110.53:com.pica.cloud.account/pica-cloud-account into dev-login0218

# Conflicts:
#	server/src/main/java/com/pica/cloud/account/account/server/service/impl/LoginServiceImpl.java
......@@ -152,6 +152,12 @@
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.pica.cloud.patient</groupId>
<artifactId>pica-cloud-smartcontract-client</artifactId>
......
......@@ -7,11 +7,13 @@ import com.pica.cloud.account.account.server.exception.AccountException;
import com.pica.cloud.account.account.server.log.AccountLogEntityUtils;
import com.pica.cloud.account.account.server.log.AccountLogUtils;
import com.pica.cloud.account.account.server.req.BaseRequest;
import com.pica.cloud.account.account.server.req.OneClickLoginReq;
import com.pica.cloud.account.account.server.service.DoctorService;
import com.pica.cloud.account.account.server.service.LoginService;
import com.pica.cloud.account.account.server.service.TokenService;
import com.pica.cloud.account.account.server.util.AccountUtils;
import com.pica.cloud.account.account.server.util.CryptoUtil;
import com.pica.cloud.account.account.server.vo.OneClickLoginResultVo;
import com.pica.cloud.foundation.entity.PicaResponse;
import com.pica.cloud.foundation.redis.CacheClient;
import com.pica.cloud.foundation.redis.ICacheClient;
......@@ -233,4 +235,13 @@ public class LoginController extends AccountBaseController {
return PicaResponse.toResponse(loginService.loginByAppleStep(request));
}
@ApiOperation(value = "app端手机号码一键登录")
@PostMapping("/login/one-click")
public PicaResponse<LoginResult> oneClickLogin(@RequestBody EncryptEntity entity) throws Exception {
OneClickLoginReq req = CryptoUtil.decrypt(entity, OneClickLoginReq.class);
req.setType(super.getSourceType());
LoginResult oneClickLoginResultVo = loginService.oneClickLogin(req);
return PicaResponse.toResponse(oneClickLoginResultVo);
}
}
package com.pica.cloud.account.account.server.entity;
/**
* @program: pica-cloud-account
* @description:
* @author: wfy
* @create: 2020-02-12 17:09
*/
public class MobileDataEntity {
private String mobileName;
private String tradeNo;
private Integer fanqizha;
private String tag;
public String getMobileName() {
return mobileName;
}
public void setMobileName(String mobileName) {
this.mobileName = mobileName;
}
public String getTradeNo() {
return tradeNo;
}
public void setTradeNo(String tradeNo) {
this.tradeNo = tradeNo;
}
public Integer getFanqizha() {
return fanqizha;
}
public void setFanqizha(Integer fanqizha) {
this.fanqizha = fanqizha;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
package com.pica.cloud.account.account.server.entity;
/**
* @program: pica-cloud-account
* @description:
* @author: wfy
* @create: 2020-02-12 17:06
*/
public class QueryMobileEntity {
private String code;
private String message;
private Integer chargeStatus;
private MobileDataEntity data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Integer getChargeStatus() {
return chargeStatus;
}
public void setChargeStatus(Integer chargeStatus) {
this.chargeStatus = chargeStatus;
}
public MobileDataEntity getData() {
return data;
}
public void setData(MobileDataEntity data) {
this.data = data;
}
@Override
public String toString() {
return "QueryMobileEntity{" +
"code='" + code + '\'' +
", message='" + message + '\'' +
", chargeStatus=" + chargeStatus +
", data=" + data +
'}';
}
}
package com.pica.cloud.account.account.server.model;
import com.pica.cloud.account.account.server.entity.MobileDataEntity;
import com.pica.cloud.account.account.server.entity.QueryMobileEntity;
import com.pica.cloud.account.account.server.util.AESUtil;
import com.pica.cloud.account.account.server.util.HttpUtil;
import com.pica.cloud.account.account.server.util.MD5;
import com.pica.cloud.account.account.server.util.RSAUtil;
import com.pica.cloud.account.account.server.util.SignUtils;
import com.pica.cloud.foundation.entity.PicaException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @program: pica-cloud-account
* @description:
* @author: wfy
* @create: 2020-02-24 13:57
*/
@Component
public class OneClickProcessor {
private static final String DEFAULT_ENCRYPT_TYPE = "0";
private Logger logger = LoggerFactory.getLogger(this.getClass());
//手机号加解密方式 0 AES 1 RSA , 可以不传,不传则手机号解密直接使用AES解密
private String aesEncryptType = DEFAULT_ENCRYPT_TYPE;
private String rsaEncryptType = "1";
private String encryptType = DEFAULT_ENCRYPT_TYPE;
//创建应用时填入的rsa公钥对应的私钥字符串
public static final String privateKey = "";
@Value("${shanyan.url.mobilequery}")
private String mobileQueryUrl;
@Value("${shanyan.android.appId}")
private String androidAppId;
@Value("${shanyan.android.appKey}")
private String androidAppKey;
@Value("${shanyan.ios.appId}")
private String iosAppId;
@Value("${shanyan.ios.appKey}")
private String iosAppKey;
@Autowired
public String tokenExchangeMobile(String token, Integer type) {
if (type == null) {
return null;
}
String appId;
String appKey;
if (type.equals(1)) {
appId = androidAppId;
appKey = androidAppKey;
} else if (type.equals(2)) {
appId = iosAppId;
appKey = iosAppKey;
} else {
return null;
}
String returnMobile = null;
//从SDK获取的token参数
try {
Map<String, String> params = new HashMap<String, String>();
params.put("token", token);
params.put("appId", appId);
params.put("encryptType", encryptType);//可以不传,不传则解密直接使用AES解密
params.put("sign", SignUtils.getSign(params, appKey));
QueryMobileEntity queryMobileEntity = (QueryMobileEntity) HttpUtil.postForm(mobileQueryUrl, params, QueryMobileEntity.class);
if (null != queryMobileEntity) {
String code = queryMobileEntity.getCode(); //返回码 200000为成功
if ("200000".equals(code)) {
MobileDataEntity mobileDataEntity = queryMobileEntity.getData();
String mobile = mobileDataEntity.getMobileName();
if (aesEncryptType.equals(encryptType)) {
String key = MD5.getMD5Code(appKey);
mobile = AESUtil.decrypt(mobile, key.substring(0, 16), key.substring(16));
} else if (rsaEncryptType.equals(encryptType)) {
mobile = RSAUtil.decryptByPrivateKeyForLongStr(mobile, privateKey);
}
mobileDataEntity.setMobileName(mobile);
returnMobile = mobileDataEntity.getMobileName();
} else {
throw new RuntimeException();
}
}
} catch (Exception e) {
logger.error(e.getMessage());
throw new PicaException("token换取手机号调用失败!");
}
return returnMobile;
}
}
package com.pica.cloud.account.account.server.req;
/**
* @program: pica-cloud-account
* @description:
* @author: wfy
* @create: 2020-02-12 15:58
*/
public class OneClickLoginReq {
private Integer type;
private String token = "";
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
package com.pica.cloud.account.account.server.req;
/**
* @program: pica-cloud-account
* @description:
* @author: wfy
* @create: 2020-02-12 17:11
*/
public class QueryMobileReq {
private String token;
private String appId;
private String clientIp;
private String encryptType;
private String outId;
private String sign;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getEncryptType() {
return encryptType;
}
public void setEncryptType(String encryptType) {
this.encryptType = encryptType;
}
public String getOutId() {
return outId;
}
public void setOutId(String outId) {
this.outId = outId;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
}
......@@ -8,6 +8,8 @@ import com.pica.cloud.foundation.entity.PicaResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import com.pica.cloud.account.account.server.req.OneClickLoginReq;
import com.pica.cloud.account.account.server.vo.OneClickLoginResultVo;
public interface LoginService {
/**
......@@ -68,6 +70,8 @@ public interface LoginService {
*/
UnifiedVerificationResp preLoginValidate(BaseRequest request);
LoginResult oneClickLogin(OneClickLoginReq req);
/**
* @Description 苹果登录授权
* @Author Chongwen.jiang
......
......@@ -13,7 +13,9 @@ import com.pica.cloud.account.account.server.enums.BizTypeRespEnum;
import com.pica.cloud.account.account.server.log.AccountLogEntityUtils;
import com.pica.cloud.account.account.server.log.AccountLogUtils;
import com.pica.cloud.account.account.server.mapper.*;
import com.pica.cloud.account.account.server.model.OneClickProcessor;
import com.pica.cloud.account.account.server.req.BaseRequest;
import com.pica.cloud.account.account.server.req.OneClickLoginReq;
import com.pica.cloud.account.account.server.resp.UnifiedVerificationResp;
import com.pica.cloud.account.account.server.service.DoctorService;
import com.pica.cloud.account.account.server.service.LoginService;
......@@ -22,6 +24,7 @@ import com.pica.cloud.account.account.server.util.AESUtil;
import com.pica.cloud.account.account.server.util.AccountUtils;
import com.pica.cloud.account.account.server.util.TokenUtils;
import com.pica.cloud.account.account.server.util.WeChatUtils;
import com.pica.cloud.account.account.server.vo.OneClickLoginResultVo;
import com.pica.cloud.foundation.encryption.common.constants.EncryptConstants;
import com.pica.cloud.foundation.encryption.util.EncryptUtils;
import com.pica.cloud.foundation.entity.PicaException;
......@@ -38,6 +41,13 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.PublicKey;
import java.util.Date;
import java.util.HashMap;
......@@ -84,6 +94,9 @@ public class LoginServiceImpl implements LoginService {
@Autowired
private AccountAppleInfoMapper accountAppleInfoMapper;
@Autowired
private OneClickProcessor oneClickProcessor;
@Value("${doubleWritingMode}")
private boolean doubleWritingMode;
......@@ -471,6 +484,26 @@ public class LoginServiceImpl implements LoginService {
return doctor;
}
@Override
public LoginResult oneClickLogin(OneClickLoginReq req) {
OneClickLoginResultVo o = new OneClickLoginResultVo();
String mobile = oneClickProcessor.tokenExchangeMobile(req.getToken(),req.getType());
if(StringUtils.isBlank(mobile)){
}
AccountInfoEntity accountInfoEntity = accountInfoDetailMapper.selectByMobile(AESUtil.encryptV0(mobile));
BaseRequest baseRequest = new BaseRequest();
if (accountInfoEntity == null) {
//说明是注册功能
accountUtils.checkRegisterMobilePhoneAndAuthCode(mobile, baseRequest.getFlag() + "", baseRequest.getAuthCode());
return registerService.register(baseRequest);
} else {
//登录功能
accountUtils.checkMobilePhoneAndAuthCode(baseRequest.getMobile(), AccountTypeEnum.SYSCODE_TYPE_LOGIN.getCode() + "", baseRequest.getAuthCode());
return processLogin(baseRequest, accountInfoEntity.getId(), AccountTypeEnum.LOGIN_CODE.getCode());
}
}
private String processDoctorAvatar(String avatar_image_url) {
if (StringUtils.isEmpty(avatar_image_url)) {
return DEFAULT_DOCTOR_PICTURE_URL;
......
......@@ -9,6 +9,7 @@ import sun.misc.BASE64Decoder;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.util.ArrayList;
......@@ -44,7 +45,7 @@ public class AESUtil {
"ZeGM+y23aTArHCMOPWIpleTuWO7FU4r7EdSr3RkCQQCliu4CwyhRY33H210U81memgFLYnAMEEce7qxgrqs+T4Gqa/lJy8BVqZGxkAA2xJfwA7f" +
"UJN9i7zdvvxJJ/wB5AkA+OKfnTXTp8qF4lZiVMrGl3d5sgg87q1DhC5XruviH6a3u6JOLlRNQy2+TGxzWMYaJ1RwEfygqBYOgyvoqNR3Q";
private static final String charset = "UTF-8";
/**
* aes解密
* @param encrypt 内容
......@@ -175,6 +176,28 @@ public class AESUtil {
return EncryptCreateUtil.dencrypt(data);
}
public static String decrypt(String sSrc, String sKey, String siv) throws Exception {
try {
if (sSrc == null || sSrc.length() == 0) {
return null;
}
if (sKey == null) {
throw new Exception("decrypt key is null");
}
if (sKey.length() != 16) {
throw new Exception("decrypt key length error");
}
byte[] Decrypt = ByteFormat.hexToBytes(sSrc);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec skeySpec = new SecretKeySpec(sKey.getBytes(charset), "AES");
IvParameterSpec iv = new IvParameterSpec(siv.getBytes(charset));//new IvParameterSpec(getIV());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);//使用解密模式初始化 密
return new String(cipher.doFinal(Decrypt), charset);
} catch (Exception ex) {
throw new Exception("decrypt errot", ex);
}
}
/**
* 测试
*/
......
package com.pica.cloud.account.account.server.util;
public final class Base64 {
/**
* Base64编码表。
*/
private static final char[] BASE64CODE = { 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '+', '/', };
/**
* Base64解码表。
*/
private static final byte[] BASE64DECODE = { -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1,
-1, // 注意两个63,为兼容SMP,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 63,
-1,
63, // “/”和“-”都翻译成63。
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, // 注意两个0:
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1,
-1, // “A”和“=”都翻译成0。
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, };
private static final int HEX_255 = 0x0000ff;
private static final int HEX_16515072 = 0xfc0000;
private static final int HEX_258048 = 0x3f000;
private static final int HEX_4032 = 0xfc0;
private static final int HEX_63 = 0x3f;
private static final int HEX_16711680 = 0xff0000;
private static final int HEX_65280 = 0x00ff00;
private static final int NUMBER_TWO = 2;
private static final int NUMBER_THREE = 3;
private static final int NUMBER_FOUR = 4;
private static final int NUMBER_SIX = 6;
private static final int NUMBER_EIGHT = 8;
private static final int NUMBER_TWELVE = 12;
private static final int NUMBER_SIXTEEN = 16;
private static final int NUMBER_EIGHTEEN = 18;
/**
* 构造方法私有化,防止实例化。
*/
private Base64() {
}
/**
* Base64编码。将字节数组中字节3个一组编码成4个可见字符。
*
* @param b
* 需要被编码的字节数据。
* @return 编码后的Base64字符串。
*/
public static String encode(byte[] b) {
int code = 0;
// 按实际编码后长度开辟内存,加快速度
StringBuffer sb = new StringBuffer(
((b.length - 1) / NUMBER_THREE) << NUMBER_TWO + NUMBER_FOUR);
// 进行编码
for (int i = 0; i < b.length; i++) {
code |= (b[i] << (NUMBER_SIXTEEN - i % NUMBER_THREE * NUMBER_EIGHT))
& (HEX_255 << (NUMBER_SIXTEEN - i % NUMBER_THREE
* NUMBER_EIGHT));
if (i % NUMBER_THREE == NUMBER_TWO || i == b.length - 1) {
sb.append(BASE64CODE[(code & HEX_16515072) >>> NUMBER_EIGHTEEN]);
sb.append(BASE64CODE[(code & HEX_258048) >>> NUMBER_TWELVE]);
sb.append(BASE64CODE[(code & HEX_4032) >>> NUMBER_SIX]);
sb.append(BASE64CODE[code & HEX_63]);
code = 0;
}
}
// 对于长度非3的整数倍的字节数组,编码前先补0,编码后结尾处编码用=代替,
// =的个数和短缺的长度一致,以此来标识出数据实际长度
if (b.length % NUMBER_THREE > 0) {
sb.setCharAt(sb.length() - 1, '=');
}
if (b.length % NUMBER_THREE == 1) {
sb.setCharAt(sb.length() - NUMBER_TWO, '=');
}
return sb.toString();
}
/**
* Base64解码。
*
* @param code
* 用Base64编码的ASCII字符串
* @return 解码后的字节数据
*/
public static byte[] decode(String code) {
// 检查参数合法性
if (code == null) {
return null;
}
int len = code.length();
if (len % NUMBER_FOUR != 0) {
throw new IllegalArgumentException(
"Base64 string length must be 4*n");
}
if (code.length() == 0) {
return new byte[0];
}
// 统计填充的等号个数
int pad = 0;
if (code.charAt(len - 1) == '=') {
pad++;
}
if (code.charAt(len - NUMBER_TWO) == '=') {
pad++;
}
// 根据填充等号的个数来计算实际数据长度
int retLen = len / NUMBER_FOUR * NUMBER_THREE - pad;
// 分配字节数组空间
byte[] ret = new byte[retLen];
// 查表解码
char ch1, ch2, ch3, ch4;
int i;
for (i = 0; i < len; i += NUMBER_FOUR) {
int j = i / NUMBER_FOUR * NUMBER_THREE;
ch1 = code.charAt(i);
ch2 = code.charAt(i + 1);
ch3 = code.charAt(i + NUMBER_TWO);
ch4 = code.charAt(i + NUMBER_THREE);
int tmp = (BASE64DECODE[ch1] << NUMBER_EIGHTEEN)
| (BASE64DECODE[ch2] << NUMBER_TWELVE)
| (BASE64DECODE[ch3] << NUMBER_SIX) | (BASE64DECODE[ch4]);
ret[j] = (byte) ((tmp & HEX_16711680) >> NUMBER_SIXTEEN);
if (i < len - NUMBER_FOUR) {
ret[j + 1] = (byte) ((tmp & HEX_65280) >> NUMBER_EIGHT);
ret[j + NUMBER_TWO] = (byte) ((tmp & HEX_255));
} else {
if (j + 1 < retLen) {
ret[j + 1] = (byte) ((tmp & HEX_65280) >> NUMBER_EIGHT);
}
if (j + NUMBER_TWO < retLen) {
ret[j + NUMBER_TWO] = (byte) ((tmp & HEX_255));
}
}
}
return ret;
}
}
package com.pica.cloud.account.account.server.util;
/**
* 格式化操作类
*/
public class ByteFormat {
private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
public ByteFormat() {
}
public static final String bytesToHexString(byte[] bArray) {
StringBuffer sb = new StringBuffer(bArray.length);
for (int i = 0; i < bArray.length; ++i) {
String sTemp = Integer.toHexString(255 & bArray[i]);
if (sTemp.length() < 2) {
sb.append(0);
}
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
public static byte[] hexToBytes(String str) {
if (str == null) {
return null;
} else {
char[] hex = str.toCharArray();
int length = hex.length / 2;
byte[] raw = new byte[length];
for (int i = 0; i < length; ++i) {
int high = Character.digit(hex[i * 2], 16);
int low = Character.digit(hex[i * 2 + 1], 16);
int value = high << 4 | low;
if (value > 127) {
value -= 256;
}
raw[i] = (byte) value;
}
return raw;
}
}
public static void main(String[] args) {
byte[] data = new byte[65536];
for (int i = 0; i < data.length; ++i) {
data[i] = (byte) i;
}
}
}
package com.pica.cloud.account.account.server.util;
import com.alibaba.fastjson.JSON;
import com.pica.cloud.foundation.utils.utils.HttpClientUtil;
import com.pica.cloud.foundation.utils.utils.StringUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.Map;
/**
* @program: pica-cloud-account
* @description:
* @author: wfy
* @create: 2020-02-12 17:45
*/
public class HttpUtil {
private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
private static final CloseableHttpClient hc;
static {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setDefaultMaxPerRoute(20);
cm.setMaxTotal(200);
hc = HttpClients.custom().setConnectionManager(cm).build();
}
public static Object postForm(String url, Map<String, String> params, Class clazz) throws IOException, URISyntaxException {
URIBuilder builder = new URIBuilder(url);
if (params != null && params.size() > 0) {
params.forEach((k, v) -> {
builder.setParameter(k, v);
});
}
HttpPost post = new HttpPost(builder.build());
CloseableHttpResponse resp = null;
Object data;
try {
resp = hc.execute(post);
String buf = IOUtils.toString(resp.getEntity().getContent(), "utf-8");
data = StringUtil.isNotNull(buf) ? JSON.parseObject(buf, clazz) : null;
} finally {
if (resp != null) {
try {
resp.close();
} catch (IOException var12) {
logger.error(var12.getMessage());
}
}
}
return data;
}
}
package com.pica.cloud.account.account.server.util;
import java.security.MessageDigest;
public class MD5 {
// 全局数组
private final static String[] strDigits = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f","g","h","j","?","~" };
// 返回形式为数字跟字符串
private static String byteToArrayString(byte bByte) {
int iRet = bByte;
if (iRet < 0) {
iRet += 256;
}
int iD1 = iRet / 16;
int iD2 = iRet % 16;
return strDigits[iD1] + strDigits[iD2];
}
// 转换字节数组为16进制字串
private static String byteToString(byte[] bByte) {
StringBuffer sBuffer = new StringBuffer();
for (int i = 0; i < bByte.length; i++) {
sBuffer.append(byteToArrayString(bByte[i]));
}
return sBuffer.toString();
}
public static String getMD5Code(String strObj) {
String resultString = null;
try {
resultString = new String(strObj);
MessageDigest md = MessageDigest.getInstance("MD5");
// md.digest() 该函数返回值为存放哈希值结果的byte数组
resultString = byteToString(md.digest(strObj.getBytes("UTF-8")));
} catch (Exception ex) {
ex.printStackTrace();
}
return resultString;
}
}
......@@ -2,12 +2,12 @@ package com.pica.cloud.account.account.server.util;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
......@@ -16,7 +16,6 @@ import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* RSA加解密工具类
*/
......@@ -39,6 +38,21 @@ public class RSAUtil {
RSAUtil.rsapublickey = rsapublickeyTemp;
}
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 加密方法
*
......@@ -121,6 +135,43 @@ public class RSAUtil {
return outStr;
}
/**
* 私钥解密
*
* @param encryptedStr 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static String decryptByPrivateKeyForLongStr(String encryptedStr, String privateKey) throws Exception {
byte[] encryptedData = ByteFormat.hexToBytes(encryptedStr);
byte[] keyBytes = com.pica.cloud.account.account.server.util.Base64.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return new String(decryptedData);
}
public static void main(String[] args) throws Exception {
//生成公钥和私钥
// genKeyPair();
......
package com.pica.cloud.account.account.server.util;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.Map;
/**
* Description:签名工具类
* User: liutao
* Date: 2019-09-11
* Time: 10:29
*/
public class SignUtils {
public static String getSign(Map<String, String> requestMap, String appKey) {
return hmacSHA256Encrypt(requestMap2Str(requestMap), appKey);
}
private static String hmacSHA256Encrypt(String encryptText, String encryptKey) {
byte[] result = null;
try {
//根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKeySpec signinKey = new SecretKeySpec(encryptKey.getBytes("UTF-8"), "HmacSHA256");
//生成一个指定 Mac 算法 的 Mac 对象
Mac mac = Mac.getInstance("HmacSHA256");
//用给定密钥初始化 Mac 对象
mac.init(signinKey);
//完成 Mac 操作
byte[] rawHmac = mac.doFinal(encryptText.getBytes("UTF-8"));
return ByteFormat.bytesToHexString(rawHmac);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String requestMap2Str(Map<String, String> requestMap) {
String[] keys = requestMap.keySet().toArray(new String[0]);
Arrays.sort(keys);
StringBuilder stringBuilder = new StringBuilder();
for (String str : keys) {
if (!str.equals("sign")) {
stringBuilder.append(str).append(requestMap.get(str));
}
}
return stringBuilder.toString();
}
}
package com.pica.cloud.account.account.server.vo;
import com.pica.cloud.account.account.server.entity.QueryMobileEntity;
/**
* @program: pica-cloud-account
* @description:
* @author: wfy
* @create: 2020-02-12 16:01
*/
public class OneClickLoginResultVo {
private QueryMobileEntity queryMobileEntity;
public QueryMobileEntity getQueryMobileEntity() {
return queryMobileEntity;
}
public void setQueryMobileEntity(QueryMobileEntity queryMobileEntity) {
this.queryMobileEntity = queryMobileEntity;
}
}
......@@ -33,15 +33,15 @@ spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#spring.jackson.default-property-inclusion=non_null
memcached.url=192.168.130.230:11211
#微信登陆
#\u5FAE\u4FE1\u767B\u9646
weChatAppID=wx5103ed453ef2dbe8
weChatAppSecret=6faa9bef3302786c08b2baf278613f38
#h5使用的云鹊医公众号
#h5\u4F7F\u7528\u7684\u4E91\u9E4A\u533B\u516C\u4F17\u53F7
weChatAppIDH5=wx08b383d002c73f26
weChatAppSecretH5=b3a6be25c9f62423b88a3d0611f060d1
weChatURL=https://api.weixin.qq.com/sns/userinfo?
#是否开启双写模式,是否需要向p_doctor表写数据
#\u662F\u5426\u5F00\u542F\u53CC\u5199\u6A21\u5F0F\uFF0C\u662F\u5426\u9700\u8981\u5411p_doctor\u8868\u5199\u6570\u636E
doubleWritingMode=true
#rabbitmq settings
......@@ -56,10 +56,10 @@ management.endpoint.health.show-details=always
# Job config begin
# 控制器地址:服务启动自动注册到控制器中
# \u63A7\u5236\u5668\u5730\u5740\uFF1A\u670D\u52A1\u542F\u52A8\u81EA\u52A8\u6CE8\u518C\u5230\u63A7\u5236\u5668\u4E2D
xxl.job.admin.addresses=http://192.168.110.124:7899/job
#执行器命名规则job-exec-<申请Port>
#\u6267\u884C\u5668\u547D\u540D\u89C4\u5219job-exec-<\u7533\u8BF7Port>
xxl.job.executor.appname=job-exec-7906
xxl.job.executor.ip=
xxl.job.executor.port=7906
......@@ -67,13 +67,10 @@ xxl.job.executor.port=7906
### xxl-job, access token
xxl.job.accessToken=
### 确保改目录可写/opt/xxl-job-logs/jobhandler
### \u786E\u4FDD\u6539\u76EE\u5F55\u53EF\u5199/opt/xxl-job-logs/jobhandler
xxl.job.executor.logpath=/opt/xxl-job-logs/jobhandler
### xxl-job log retention days
xxl.job.executor.logretentiondays=-1
pica.cloud.message.url=https://dev-sc.yunqueyi.com/message
\ No newline at end of file
spring.profiles.active=dev
# \u95EA\u9A8C\u4E00\u952E\u767B\u5F55\u914D\u7F6E
shanyan.url.mobilequery=https://api.253.com/open/flashsdk/mobile-query
shanyan.android.appId=BQwEYJht
shanyan.android.appKey=6KizWzXr
shanyan.ios.appId=XcdiWema
shanyan.ios.appKey=psIOYIa4
\ No newline at end of file
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册