Authored by zhaoyue

Merge branch 'zhaoyue-dev2' into 'master'

Zhaoyue dev2



See merge request !27
... ... @@ -2,8 +2,8 @@ git pull
git add --all src/main/java/*
git add push.sh
git add pom.xml
git commit -m "add qrcode related code"
git push origin master
#git push origin zhaoyue-dev
git commit -m "add qr related code"
#git push origin master
git push origin zhaoyue-dev2
git status
git pull
... ...
... ... @@ -76,5 +76,7 @@ public interface Constants {
public static final double SMALL_DOUBLE = 0.001;
public static final String WEB_LOGIN_URL = "http://testingurl/?qrcode=";
public static final String WEB_LOGIN_URL = "http://testingurl/?url=";
public static final String LOCAL_QRVERIFY_URL = "https://www.hanhezy.com:8090/qrcode/getUsrInfoWithQr?encryptQr=";
}
... ...
... ... @@ -33,7 +33,10 @@ public enum ResultStatus {
DB_ERROR(-11160,"服务器错误,无法写入数据库/Server error, can not write into database"),
COMPANY_ERROR(-11170,"用户所属公司信息有误/Company infomation error");
COMPANY_ERROR(-11170,"用户所属公司信息有误/Company information error"),
// 112开头的与QR Code有关
INVALID_QR_CODE(-11201,"无效QR码/Invalid QR code");
... ...
... ... @@ -23,7 +23,10 @@ import com.xkl.repository.XklMemberRespository;
import com.xkl.security.AntiXSS;
import com.xkl.service.ILoginService;
import com.xkl.service.IQRCodeService;
import com.xkl.service.QRCodeServiceImpl;
import com.xkl.tools.DESTools;
import com.xkl.tools.DatetimeTools;
import com.xkl.tools.HttpTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
... ... @@ -34,6 +37,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
... ... @@ -123,8 +127,13 @@ public class QRCodeController {
@AntiXSS
@RequestMapping(value = "/getUsrInfoWithQr", method = RequestMethod.GET)
@ApiOperation(value = "使用qrcode查询个人信息")
// 接口返回的qrcode都是正常的qrcode,但是客户端使用的时候必须加密才能使用。
public ResponseEntity<ResultModel> getUsrInfoWithQr(HttpServletRequest request,
@RequestParam String qrcode, @RequestParam long t) {
@RequestParam String encryptQr, @RequestParam long t) {
String qrcode = qrCodeService.getDecryptHttpParaQr(encryptQr, t);
if (qrcode == null) {
return new ResponseEntity<>(ResultModel.error(ResultStatus.INVALID_QR_CODE), HttpStatus.OK);
}
String account = qrCodeService.getAccountWithQRCode(qrcode);
User user = userRepository.findByLoginAccountAndStatus(account, true);
if (user == null) {
... ... @@ -144,6 +153,13 @@ public class QRCodeController {
}
private static String genWebloginUrl(String qrcode) {
return Constants.WEB_LOGIN_URL + qrcode.trim();
String now = HttpTools.getNow();
try {
String encryptQr = DESTools.encrypt(qrcode.trim() + now, QRCodeServiceImpl.getHttpParaQrKey());
String interUrl = Constants.LOCAL_QRVERIFY_URL + encryptQr + "&t=" + now;
return Constants.WEB_LOGIN_URL + URLEncoder.encode(interUrl, "utf-8");
} catch (Exception e) {
return null;
}
}
}
... ...
... ... @@ -7,4 +7,6 @@ public interface IQRCodeService {
public String getQRCodeWithAccount(String account);
public String getAccountWithQRCode(String qrcode);
public String getDecryptHttpParaQr(String encryptQr, long t);
}
\ No newline at end of file
... ...
... ... @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit;
public class QRCodeServiceImpl implements IQRCodeService, Constants {
private static final String REDIS_ACC_QR_PREFIX = "acc_qr-";
private static final String REDIS_QR_ACC_PREFIX = "qr_acc-";
private static final String HTTP_PARA_QR_KEY = "tnvkqybFHp69pinDZJ7UWuX7";
private RedisTemplate<String, String> redis;
... ... @@ -29,6 +30,23 @@ public class QRCodeServiceImpl implements IQRCodeService, Constants {
this.redis = redis;
}
@Override
public String getDecryptHttpParaQr(String encryptQr, long t) {
String qrcode = "";
try {
String str = DESTools.decrypt(encryptQr, HTTP_PARA_QR_KEY);
if (str.endsWith(Long.toString(t))) {
return str.replace(Long.toString(t), "");
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public String getAccountWithQRCode(String qrcode) {
String qrAcckey = genQrAccKey(qrcode);
... ... @@ -69,4 +87,7 @@ public class QRCodeServiceImpl implements IQRCodeService, Constants {
return REDIS_QR_ACC_PREFIX + account;
}
public static String getHttpParaQrKey() {
return HTTP_PARA_QR_KEY;
}
}
... ...
... ... @@ -12,7 +12,7 @@ import java.util.Random;
*/
public class DESTools {
/**
* 加密、解密key.
* 加密、解密key,用作生成二维码之用,无其他用途。
*/
private static final String PASSWORD_CRYPT_KEY = "HhiTuqm7lsMVHYD4Bkj2B5jSUh0IKPNk";
... ... @@ -66,6 +66,20 @@ public class DESTools {
}
/**
* 对数据进行DES加密.
*
* @param data 待进行DES加密的数据
* @return 返回经过DES加密后的数据
* @throws Exception
* @author <a href="mailto:xiexingxing1121@126.com" mce_href="mailto:xiexingxing1121@126.com">AmigoXie</a>
* Creation date: 2007-7-31 - 下午12:06:24
*/
public final static String decrypt(String data, String key) throws Exception {
return new String(decrypt(hex2byte(data.getBytes()),
key.getBytes()));
}
/**
* 对用DES加密过的数据进行解密.
*
* @param data DES加密数据
... ... @@ -79,6 +93,22 @@ public class DESTools {
.getBytes()));
}
/**
* 对用DES加密过的数据进行解密.
*
* @param data DES加密数据
* @return 返回解密后的数据
* @throws Exception
* @author <a href="mailto:xiexingxing1121@126.com" mce_href="mailto:xiexingxing1121@126.com">AmigoXie</a>
* Creation date: 2007-7-31 - 下午12:07:54
*/
public final static String encrypt(String data, String key) throws Exception {
return byte2hex(encrypt(data.getBytes(), key
.getBytes()));
}
/**
* 用指定的key对数据进行DES加密.
*
... ...
package com.xkl.tools;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
/**
* Created by win7 on 2016/12/25.
*/
public class HttpTools {
/**
* 获取当前时间,10位
* @return
*/
public static String getNow(){
Calendar c = Calendar.getInstance();//可以对每个时间域单独修改
return String.valueOf(c.getTimeInMillis()/1000);
}
/**
* 发送http请求
* @param url 请求url
* @param type 请求类型:GET,POST,DELETE
* @param params 请求参数:map类型
* @return
*/
public static String requestByMapWithToken(String url, String type, Map<String, String> params, String authorization){
String reqbody = getRequestData(params,"UTF-8").toString();
String result = requestByString(url + "?" + reqbody,type,authorization,null);
return result;
}
public static String requestByMap(String url, String type,Map<String, String> params){
return requestByMapWithToken(url,type,params,"");
}
/**
* 发送http请求
* @param url 请求url
* @param type 请求类型:GET,POST,DELETE
* @param reqbody 请求参数:String类型
* @return
*/
public static String requestByString(String url, String type, String authorization,String reqbody){
HttpURLConnection con = null;
String result = null;
try {
con = getHttpConnection( url , type, authorization);
//you can add any request body here if you want to post
if( reqbody != null){
DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes(reqbody);
out.flush();
out.close();
}
con.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String temp = null;
StringBuilder sb = new StringBuilder();
while((temp = in.readLine()) != null){
sb.append(temp).append(" ");
}
result = sb.toString();
in.close();
} catch (IOException e) {
System.out.println(e);
}
return result;
}
private static HttpURLConnection getHttpConnection(String url, String type, String authorization){
URL uri = null;
HttpURLConnection con = null;
try{
uri = new URL(url);
con = (HttpURLConnection) uri.openConnection();
con.setRequestMethod(type); //type: POST, PUT, DELETE, GET
if(type.equals("POST"))
con.setDoOutput(true);
con.setConnectTimeout(60000); //60 secs
con.setReadTimeout(60000); //60 secs
con.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
con.setRequestProperty("authorization",authorization);
}catch(Exception e){
System.out.println( "connection i/o failed" );
}
return con;
}
private static StringBuffer getRequestData(Map<String, String> params, String encode) {
StringBuffer stringBuffer = new StringBuffer(); //存储封装好的请求体信息
try {
for(Map.Entry<String, String> entry : params.entrySet()) {
stringBuffer.append(entry.getKey())
.append("=")
.append(URLEncoder.encode(entry.getValue(), encode))
.append("&");
}
stringBuffer.deleteCharAt(stringBuffer.length() - 1); //删除最后的一个"&"
} catch (Exception e) {
e.printStackTrace();
}
return stringBuffer;
}
}
... ...
package com.xkl.tools;
/**
* Created by zhaoyue on 2017/3/13.
*/
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import javax.crypto.Cipher;
public class RSATools {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
HashMap<String, Object> map = RSATools.getKeys();
//生成公钥和私钥
RSAPublicKey publicKey = (RSAPublicKey) map.get("public");
RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");
//模
String modulus = publicKey.getModulus().toString();
//公钥指数
String public_exponent = publicKey.getPublicExponent().toString();
//私钥指数
String private_exponent = privateKey.getPrivateExponent().toString();
//明文
String ming = "123456789";
//使用模和指数生成公钥和私钥
RSAPublicKey pubKey = RSATools.getPublicKey(modulus, public_exponent);
RSAPrivateKey priKey = RSATools.getPrivateKey(modulus, private_exponent);
//加密后的密文
String mi = RSATools.encryptByPublicKey(ming, pubKey);
System.err.println(mi);
//解密后的明文
ming = RSATools.decryptByPrivateKey(mi, priKey);
System.err.println(ming);
}
/**
* 生成公钥和私钥
*
* @throws NoSuchAlgorithmException
*/
public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException {
HashMap<String, Object> map = new HashMap<String, Object>();
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
map.put("public", publicKey);
map.put("private", privateKey);
return map;
}
/**
* 使用模和指数生成RSA公钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus 模
* @param exponent 指数
* @return
*/
public static RSAPublicKey getPublicKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 使用模和指数生成RSA私钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus 模
* @param exponent 指数
* @return
*/
public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 公钥加密
*
* @param data
* @param publicKey
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 模长
int key_len = publicKey.getModulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
String[] datas = splitString(data, key_len - 11);
String mi = "";
//如果明文长度大于模长-11则要分组加密
for (String s : datas) {
mi += bcd2Str(cipher.doFinal(s.getBytes()));
}
return mi;
}
/**
* 私钥解密
*
* @param data
* @param privateKey
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey)
throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//模长
int key_len = privateKey.getModulus().bitLength() / 8;
byte[] bytes = data.getBytes();
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
System.err.println(bcd.length);
//如果密文长度大于模长则要分组解密
String ming = "";
byte[][] arrays = splitArray(bcd, key_len);
for (byte[] arr : arrays) {
ming += new String(cipher.doFinal(arr));
}
return ming;
}
/**
* ASCII码转BCD码
*/
public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
byte[] bcd = new byte[asc_len / 2];
int j = 0;
for (int i = 0; i < (asc_len + 1) / 2; i++) {
bcd[i] = asc_to_bcd(ascii[j++]);
bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
}
return bcd;
}
public static byte asc_to_bcd(byte asc) {
byte bcd;
if ((asc >= '0') && (asc <= '9'))
bcd = (byte) (asc - '0');
else if ((asc >= 'A') && (asc <= 'F'))
bcd = (byte) (asc - 'A' + 10);
else if ((asc >= 'a') && (asc <= 'f'))
bcd = (byte) (asc - 'a' + 10);
else
bcd = (byte) (asc - 48);
return bcd;
}
/**
* BCD转字符串
*/
public static String bcd2Str(byte[] bytes) {
char temp[] = new char[bytes.length * 2], val;
for (int i = 0; i < bytes.length; i++) {
val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
val = (char) (bytes[i] & 0x0f);
temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
}
return new String(temp);
}
/**
* 拆分字符串
*/
public static String[] splitString(String string, int len) {
int x = string.length() / len;
int y = string.length() % len;
int z = 0;
if (y != 0) {
z = 1;
}
String[] strings = new String[x + z];
String str = "";
for (int i = 0; i < x + z; i++) {
if (i == x + z - 1 && y != 0) {
str = string.substring(i * len, i * len + y);
} else {
str = string.substring(i * len, i * len + len);
}
strings[i] = str;
}
return strings;
}
/**
* 拆分数组
*/
public static byte[][] splitArray(byte[] data, int len) {
int x = data.length / len;
int y = data.length % len;
int z = 0;
if (y != 0) {
z = 1;
}
byte[][] arrays = new byte[x + z][];
byte[] arr;
for (int i = 0; i < x + z; i++) {
arr = new byte[len];
if (i == x + z - 1 && y != 0) {
System.arraycopy(data, i * len, arr, 0, y);
} else {
System.arraycopy(data, i * len, arr, 0, len);
}
arrays[i] = arr;
}
return arrays;
}
}
\ No newline at end of file
... ...