v5行为验证使用介绍(四)- Verify5Client.java

目录

v5行为验证使用介绍(一)- 试探攻击的威胁
v5行为验证使用介绍(二)- 应用管理
v5行为验证使用介绍(三)- 程序接入流程
v5行为验证使用介绍(四)- Verify5Client.java

用法

这个类封装了v5应用端定时刷新token、获取host、二次验证的行为,内置了签名算法的实现。实际使用时,可将Verify5Client作为单例对象来管理。例如:

  • 应用启动时初始化
String host="从控制台获取域名";
String appid="从控制台获取APP ID";
String appkey="从控制台获取APP Key";
Verify5Client v5client=new Verify5Client(host,appid, appkey);
v5client.init();//启动一个Timer定时刷新token

  • 手动刷新token(一般无需手动刷新)
v5client.refreshToken();
  • 获取token和domain
Map<String, String> data = v5client.getTokenData();
String token=data.get("token");
String domain=data.get("domain");
//TODO 传给前端生成验证

代码


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.codec.digest.DigestUtils;

import com.google.gson.Gson;

public class Verify5Client {

	private Timer timer = new Timer();

	private String appid;

	private String appkey;

	private String host;

	public Verify5Client(String host,String appid,String appkey) {
		this.appid=appid;
		this.appkey=appkey;
		this.host=host;
	}
	
	public boolean sveirfy(String verifyId, Map<String,String> extra) throws Exception {
		String token=getTokenData().get("token");
		Map<String,String> params=new HashMap<>();
		if(extra!=null) {
			params.putAll(extra);
		}
		params.put("token", token);
		params.put("verifyid", verifyId);
		params.put("timestamp", ""+System.currentTimeMillis());
		String sign=calcSignature(appkey, params);
		params.put("signature", sign);
		try {
			String baseurl="https://"+host;
			String json=get(baseurl,"/openapi/verify",params);
			System.out.println(json);
			return true;
		} catch (Exception e) {
			throw e;
		}
	}
	
	private String get(String baseurl,String relativeurl,Map<String,String> params) throws Exception{
		StringBuffer urlbuf=new StringBuffer();
		urlbuf.append(baseurl).append(relativeurl);
		if(!params.isEmpty()) {
			urlbuf.append("?");
			for(Entry<String, String> entry:params.entrySet()) {
				String key=entry.getKey();
				String value=entry.getValue();
				try {
					urlbuf.append("&").append(key).append("=").append(URLEncoder.encode(value, "UTF-8"));
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
		}
		String url=urlbuf.toString();
		System.out.println("Requesting "+url);
		BufferedReader r = null;
		HttpURLConnection conn =null;
		try {
			URL u = new URL(url);
			conn =  (HttpURLConnection) u.openConnection();
			conn.setConnectTimeout(5 * 1000);
			conn.setReadTimeout(30 * 1000);
			if(url.startsWith("https:")) {
				HttpsURLConnection https = (HttpsURLConnection)conn;
				https.setHostnameVerifier(DO_NOT_VERIFY);
				trustAllHosts(https);
			}
			conn.connect();
			r = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			StringBuffer buf = new StringBuffer();
			String line = null;
			while ((line = r.readLine()) != null) {
				buf.append(line).append("\n");
			}
			return buf.toString();
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
			if (r != null) {
				try {
					r.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(conn!=null) {
				conn.disconnect();
			}
		}
	}
	
	@SuppressWarnings("unchecked")
	public void refreshToken() {
		Map<String,String> params=new HashMap<>();
		long time = java.util.Calendar.getInstance().getTime().getTime();
		params.put("appid", appid);
		params.put("timestamp", ""+time);
		try {
			/**计算签名*/
			Map<String ,String> signMap = new HashMap<String,String>();
			signMap.put("appid",appid);
			signMap.put("timestamp",String.valueOf(time));
			String signature=calcSignature(appkey,signMap);
			params.put("signature", signature);
			String baseurl="https://"+host;
			String json = get(baseurl,"/openapi/getToken", params);
			Gson gson=new Gson();
			System.out.println(json);
			Map<String,Object> map = gson.fromJson(json, Map.class);
			boolean success=(boolean) map.get("success");
			if(success) {
				Map<String,String> data=(Map<String, String>) map.get("data");
				if(data!=null&&data.containsKey("expiresIn")&&data.containsKey("token")) {
					String sExpiresIn=data.get("expiresIn");
					long expiresIn=Long.valueOf(sExpiresIn);
					long expiresTime=System.currentTimeMillis()+expiresIn;
					data.put("expiresTime", ""+expiresTime);
					tokenData=data;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 生成签名信息
	 * @param secretKey 产品私钥
	 * @param params 接口请求参数名和参数值map,不包括signature参数名
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public String calcSignature(String appkey, Map<String, String> params) throws UnsupportedEncodingException{
	    // 1. 参数名按照ASCII码表升序排序
	    String[] keys = params.keySet().toArray(new String[0]);
	    Arrays.sort(keys);

	    // 2. 按照排序拼接参数名与参数值
	    StringBuilder sb = new StringBuilder();
	    for (String key : keys) {
	        sb.append(key).append(params.get(key));
	    }
	    // 3. 将appKey拼接到最后
	    sb.append(appkey);

	    // 4. MD5是128位长度的摘要算法,转换为十六进制之后长度为32字符
	    return DigestUtils.md5Hex(sb.toString().getBytes("UTF-8"));
	}
	
	private static final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
		public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			return new java.security.cert.X509Certificate[] {};
		}

		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}
	} };

	private static SSLSocketFactory trustAllHosts(HttpsURLConnection connection) {
		SSLSocketFactory oldFactory = connection.getSSLSocketFactory();
		try {
			SSLContext sc = SSLContext.getInstance("TLS");
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
			SSLSocketFactory newFactory = sc.getSocketFactory();
			connection.setSSLSocketFactory(newFactory);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return oldFactory;
	};

	private static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};

	private Map<String,String> tokenData=null;

	public Map<String,String> getTokenData(){
		return tokenData;
	}
	
	public void destroy() {
		timer.purge();
	}

	public void init() {
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				refreshToken();
			}
		}, 10*1000, 60 * 60 * 1000);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值