提交 8ecde431 编写于 作者: wfy's avatar wfy

闪验:登录demo

上级 c5ee68c9
流水线 #21508 已失败 于阶段
in 0 second
......@@ -151,6 +151,12 @@
<artifactId>xxl-job-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.8.1</version>
</dependency>
</dependencies>
<dependencyManagement>
......
......@@ -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;
......@@ -206,4 +208,12 @@ public class LoginController extends AccountBaseController {
}
return PicaResponse.toResponse(resultWeb);
}
@ApiOperation(value = "app端手机号码一键登录")
@PostMapping("/login/one-click")
public PicaResponse<OneClickLoginResultVo> oneClickLogin(@RequestBody OneClickLoginReq req){
OneClickLoginResultVo oneClickLoginResultVo = new OneClickLoginResultVo();
oneClickLoginResultVo = loginService.oneClickLogin(req);
return PicaResponse.toResponse(oneClickLoginResultVo);
}
}
......@@ -3,6 +3,8 @@ package com.pica.cloud.account.account.server.service;
import com.pica.cloud.account.account.server.entity.LoginResult;
import com.pica.cloud.account.account.server.entity.PICAPDoctor;
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.vo.OneClickLoginResultVo;
public interface LoginService {
/**
......@@ -52,4 +54,6 @@ public interface LoginService {
String bindWeChat(long doctorId, BaseRequest request);
PICAPDoctor queryDoctor(long doctorId);
OneClickLoginResultVo oneClickLogin(OneClickLoginReq req);
}
package com.pica.cloud.account.account.server.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.internal.SignUtils;
import com.pica.cloud.account.account.server.entity.*;
import com.pica.cloud.account.account.server.enums.AccountExceptionEnum;
import com.pica.cloud.account.account.server.enums.AccountTypeEnum;
......@@ -8,18 +10,28 @@ 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.req.BaseRequest;
import com.pica.cloud.account.account.server.req.OneClickLoginReq;
import com.pica.cloud.account.account.server.req.QueryMobileReq;
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.RegisterService;
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.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.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;
import com.pica.cloud.foundation.redis.ICacheClient;
import com.pica.cloud.foundation.utils.utils.HttpClientUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -27,10 +39,15 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import static com.pica.cloud.account.account.server.util.AESUtil.privateKey;
@Service
public class LoginServiceImpl implements LoginService {
......@@ -82,6 +99,11 @@ public class LoginServiceImpl implements LoginService {
private static final String DEFAULT_DOCTOR_PICTURE_URL = "/File/doctor_default.png";
public static Map<String, String> PIC_TYPE_MAP = new HashMap();
// 免密登录后台url
public static final String FLASH_LOGIN_URL = "https://api.253.com/open/flashsdk/mobile-query";
//创建应用时填入的rsa公钥对应的私钥字符串
public static final String privateKey = "";
static {
PIC_TYPE_MAP.put("jpg", "FFD8FF");
PIC_TYPE_MAP.put("jpeg", "FFD8FF");
......@@ -379,6 +401,66 @@ public class LoginServiceImpl implements LoginService {
return doctor;
}
@Override
public OneClickLoginResultVo oneClickLogin(OneClickLoginReq req) {
OneClickLoginResultVo o = new OneClickLoginResultVo();
//应用对应的闪验APPID
String appId = "";
//应用对应的闪验APPKEY
String appKey = "";
if(0 == req.getType()){
appId = "BQwEYJht";
appKey = "6KizWzXr";
}else{
appId = "XcdiWema";
appKey = "psIOYIa4";
}
//手机号加解密方式 0 AES 1 RSA , 可以不传,不传则手机号解密直接使用AES解密
String encryptType = "0";
//从SDK获取的token参数
String token = req.getToken();
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", com.pica.cloud.account.account.server.util.SignUtils.getSign(params, appKey));
QueryMobileEntity queryMobileEntity = (QueryMobileEntity) HttpUtil.postForm(FLASH_LOGIN_URL,params,QueryMobileEntity.class);
if (null != queryMobileEntity) {
System.out.println("response:" + queryMobileEntity);
String code = queryMobileEntity.getCode(); //返回码 200000为成功
String message = queryMobileEntity.getMessage();//返回消息
Integer chargeStatus = queryMobileEntity.getChargeStatus(); //是否收费
if ("200000".equals(code)) {
MobileDataEntity mobileDataEntity = queryMobileEntity.getData();
String mobile = mobileDataEntity.getMobileName();
String tradeNo = mobileDataEntity.getTradeNo();//交易流水号
if ("0".equals(encryptType)) {
String key = MD5.getMD5Code(appKey);
mobile = AESUtil.decrypt(mobile, key.substring(0, 16), key.substring(16));
} else if ("1".equals(encryptType)) {
mobile = RSAUtil.decryptByPrivateKeyForLongStr(mobile, privateKey);
}
System.out.println("mobile:" + mobile); //解密后的手机号码
o.setMobile(mobile);
o.setFanqizha(mobileDataEntity.getFanqizha());
o.setTag(mobileDataEntity.getTag());
o.setTradeNo(tradeNo);
o.setMessage(message);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
public static void main(String[] args) {
LoginServiceImpl l = new LoginServiceImpl();
OneClickLoginReq req = new OneClickLoginReq();
l.oneClickLogin(req);
}
private String processDoctorAvatar(String avatar_image_url) {
if (StringUtils.isEmpty(avatar_image_url)) {
return DEFAULT_DOCTOR_PICTURE_URL;
......@@ -392,4 +474,6 @@ public class LoginServiceImpl implements LoginService {
}
}
}
}
......@@ -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);
}
}
/**
* 测试
*/
......
......@@ -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();
......
......@@ -21,7 +21,7 @@ eureka.instance.hostname=${spring.cloud.client.ipAddress}
eureka.instance.prefer-ip-address=true
#logback settings
logging.level.ROOT=INFO
logging.path=c:/tomcat-log/${spring.application.name}
logging.path=/Users/wfy/work/pica-project/tomcat-log/${spring.application.name}
#job settings
#xxl.job.executor.appname=pica-cloud-${server.port}-account-job
#feign settings
......@@ -33,12 +33,12 @@ 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
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
......@@ -53,10 +53,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
......@@ -64,7 +64,7 @@ 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
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册