简介
硬件锁(加密狗)加密软件。与金雅特公司合作的方式是:买家公司开发一个授权程序(这里公司的授权程序:Encrypt类的encrypt()方法),进行授权管理用户锁。
注意
:LZ只演示模拟Web端的POST或GET请求过程,以达到自动化实现加密狗烧制。
需求:
公司要求,优化硬件锁加密狗的烧制过程,通过程序自动化的完成加密狗烧制,摆脱鼠标点击网页。
实战操作如下
前提:主机上部署好了SentinelEMS服务,并且插好主锁和子锁
全局变量
模拟请求的时候需要IP,会话ID、COOKIE、用户名、密码、产品id、功能id、产品名等数据。
private static String reqIP = "http://localhost:8080/";
private static String req80 = "http://localhost:8080";
private static String reqEmsIP = "http://127.0.0.1:1947/";
private static String reqHostIP = "localhost:8080";
private static String reqHostEmsIP = "127.0.0.1:1947";
private static String JSESSIONID = "";
private static String COOKIES = "";
private static String USERNAME = "admin";
private static String PASSWORD = "yourPassword";
private static String ET = "";
private final static String PRODUCTID = "yourProductId";
private final static String FEATUREID = "yourFeatureId";
private final static String PRODUCTNAME = "yourProductName";
main方法
需要注意的是26157
是自己主锁的ID
public static void main(String[] args) throws InterruptedException, IOException {
//校验加密狗是否插入;
String dogId = "";
String isJoin = getRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/keys?rndNo=" + System.currentTimeMillis()),0);
if(isJoin.contains("error")){
System.out.println("请先插入加密狗!");
Thread.sleep ( 3000 ) ;
return;
}else{
dogId = isJoin.substring(isJoin.indexOf("<id>")+4,isJoin.indexOf("</id>"));
}
//校验是否已经烧制了
CheckLicense check=new CheckLicense();
String numString = check.CheckIsLicense();
if("".equals(numString)){
//加密狗烧制
encryptDog(dogId);
}else{
System.out.println("该加密狗已经烧制加密过,是否格式化重做,请输入想要执行功能的数字:1.是,0.否");
Scanner scanIn = new Scanner(System.in);
String number = scanIn.nextLine();
int num=Integer.parseInt(number);
if(num == 0){
System.gc();
System.exit(0);
}else if (num == 1){
//加密狗烧制
encryptDog(dogId);
}else{
System.out.println("请按指示操作!!!");
System.gc();
System.exit(0);
}
}
}
加密狗烧制
模拟post和get请求的参数和请求头中关键属性要准确
,否则返回的数据不是正确的
/**
* 加密狗烧制
*
* @param dogId 加密狗id
* @author yangz
* @date 2023/04/12
*/
public static void encryptDog(String dogId) throws InterruptedException, IOException{
//开始烧制加密狗
System.out.println("正在烧制加密狗中,请稍等。。。");
//step1:登录
// 设置请求表单数据
String data = "user_type=" + URLEncoder.encode("ISV", "UTF-8") +
"&username=" + URLEncoder.encode(USERNAME, "UTF-8") +
"&password=" + URLEncoder.encode(PASSWORD, "UTF-8") +
"&siteLanguage=" + URLEncoder.encode("zh", "UTF-8") +
"&myReferer=" + URLEncoder.encode(reqIP, "UTF-8");
postRequestApi(new URL(reqIP + "ems/verifyLogin.html"), data, true,0);
//step2:进入授权页面
getRequestApi(new URL(reqIP+"ems/loadEntitlementPage.html?rnd=" + System.currentTimeMillis()),0);
//step3:选择RORBX锁类型
getRequestApi(new URL(reqIP+"ems/getEntitlements.html?pageIndex=1&pageSize=15&sortCol=id&sortOrder=desc&searchOn=all&searchText=&vendorId=2&rnd=" + System.currentTimeMillis() / 10000),0);
//step4:进入录入锁查询锁信息
getRequestApi(new URL(reqIP+"ems/keyInfo.html?javaEnabled=false&rnd="+System.currentTimeMillis()),2);
//step5:获取C2V-nodogid信息
String c2vNoDog = getRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/keys/"+dogId+"/c2v?rndNo="+System.currentTimeMillis()),0).replaceAll("\"","\\\\\"");
//step6:获取keyinfo信息
/*StringBuffer keyinfoBuffer = new StringBuffer("[{\"c2v\":\""+c2vNoDog+"\"}]");
String keyinfoString = bufferToSpecialString(keyinfoBuffer);
String keyinfoData = "c2v=" + keyinfoString + "&ET="+URLEncoder.encode(ET, "UTF-8");
String keyinfoRep = postRequestApi(new URL(reqIP+"ems/getkeyInfoJson.html?resultentProtectionTypeId=1"),keyinfoData,false,2);*/
//step6:获取C2V信息
String c2v = getRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/keys/"+dogId+"/c2v?rndNo="+System.currentTimeMillis()+"?"+dogId),0);
//step7:点击录入锁信息
String isJSON = "c2v=" + URLEncoder.encode(c2v, "UTF-8");
String c2vinfoData = isJSON + "&ET="+URLEncoder.encode(ET, "UTF-8");
String joinLock = postRequestApi(new URL(reqIP + "ems/c2vinfo.html?isJSON=true"), c2vinfoData, false,2);
if(!joinLock.contains("No features found on key")){
//step8:格式化锁信息
StringBuffer c2vStringBuffer = new StringBuffer("[{\"haspId\":\""+dogId+"\",\"c2v\":\""+c2vNoDog+"\"}]");
String c2vString = bufferToSpecialString(c2vStringBuffer);
String recycleData = "c2v=" + c2vString + "&ET="+URLEncoder.encode(ET, "UTF-8");
String fommatRep = postRequestApi(new URL(reqIP+"ems/recycler.html?isJSON=true"),recycleData,false,2);
if(fommatRep.length()>0){
//step9:回收c2v,调用v2c
JSONArray jsonArray = new JSONArray(fommatRep);
JSONObject jsonObject = jsonArray.getJSONObject(0);
String v2cData = jsonObject.getString("v2c");
postRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/v2c"),v2cData,false,2);
}
//step10:更新c2v信息
//String c2vUpdateString = requestSentinelEms(new URL(reqEmsIP+"sentinel/ldk/v1/26157/keys/"+dogId+"/c2v?rndNo="+System.currentTimeMillis()+"?"+dogId),0);
//System.out.println(c2vUpdateString);
}
//step11:进入新增授权界面
getRequestApi(new URL(reqIP+"ems/addEntitlementPopUp.html?vendorId=2&enfId=1&pageIndex=1&rnd="+ System.currentTimeMillis()),2);
//step12:查询产品并添加
getRequestApi(new URL(reqIP+"ems/getProductsByIds.html?productIds="+PRODUCTID+"&mode=add&rnd="+ System.currentTimeMillis()),2);
//step13:获取生成HL锁的lineItemId和pkId
String formattedDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String entitlementXMLString = "<entitlement><enabled>true</enabled><action>Commit</action><isTest>false</isTest><customerId/><customerEmail/><partnerId/><partnerEmail/><refId1/><refId2/><description/><proContId/>" +
"<startDate>"+formattedDate+"</startDate><endDate>2500-12-31</endDate><identity/><policy><revocationAllowed>true</revocationAllowed><registrationRequired>DESIRED</registrationRequired></policy><entitlementItem><priority>D</priority><type>CLOUD_KEY</type><deploymentType/><featureCachingMode/><containerType>0</containerType>" +
"<startDate>"+formattedDate+"</startDate><endDate>2500-12-31</endDate><itemLicenseType>0</itemLicenseType><lineItemType>Hardware_Key</lineItemType><numActivationPerProductKey>1</numActivationPerProductKey><numProductKeys>1</numProductKeys><vendorId>2</vendorId><enforcementId>1</enforcementId><itemProduct><isRevoked>false</isRevoked>" +
"<productId>"+PRODUCTID+"</productId><product><productName>"+PRODUCTNAME+"</productName><rehost>LEAVE_AS_IS</rehost><productFeatureRef><actionName>NONE</actionName><featureId>"+FEATUREID+"</featureId><productFeatureLicenseModel><actionName>NONE</actionName><licensemodel><licenseModelId>4</licenseModelId>" +
"</licensemodel></productFeatureLicenseModel></productFeatureRef></product></itemProduct><activationAttribute><attributeName>ACKNOWLEDGEMENT_REQUEST</attributeName><attributeValue>false</attributeValue></activationAttribute>" +
"<memorySegments></memorySegments></entitlementItem></entitlement>";
//SentinelEMS服务8.4版本,跳转ems/addEntitlement.html界面的参数
String lineItem84Data = "entitlementXML=" + URLEncoder.encode(entitlementXMLString, "UTF-8") +
"&entProductDynamicMemoryDataXml="+URLEncoder.encode("<dynamicMemorySegments></dynamicMemorySegments>", "UTF-8") +
"&produceAndPush="+URLEncoder.encode("false","UTF-8")+"&lineItemTypeForProdPush=&vendorIdForProdPush=" +
"&ET="+URLEncoder.encode(ET, "UTF-8");
//SentinelEMS服务7.9版本,跳转ems/addEntitlement.html界面的参数
/*String lineItem79Data = "entitlementXML=" + URLEncoder.encode(entitlementXMLString, "UTF-8") +
"&entProductDynamicMemoryDataXml="+URLEncoder.encode("<dynamicMemorySegments></dynamicMemorySegments>", "UTF-8") +
"&ET="+URLEncoder.encode(ET, "UTF-8");*/
String lineItemRep = postRequestApi(new URL(reqIP+"ems/addEntitlement.html"),lineItem84Data,false,2);
//String lineItemRep = postRequestApi(new URL(reqIP+"ems/addEntitlement.html"),lineItem79Data,false,2);
JSONObject jsonObject = new JSONObject(lineItemRep);
int lineItemId = jsonObject.getInt("lineItemId");
JSONArray pkIds = jsonObject.getJSONArray("pkIds");
String pkId = pkIds.getString(0);
//step14:进入生成SentinelHL锁界面
getRequestApi(new URL(reqIP+"ems/updatePhysicalKey.html?id="+lineItemId+"&pkId="+pkId+"&javaEnabled=false&rnd="+ System.currentTimeMillis()),2);
//step15:烧制加密狗前打开链路
String blinkOnData = "<blink>ON</blink>";
postRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/keys/"+dogId+"/blink"),blinkOnData,false,0);
//step16:重新生成c2v
String burnC2v = getRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/keys/"+dogId+"/c2v?rndNo="+System.currentTimeMillis()),0).replaceAll("\"","\\\\\"");
//step17:烧制写入功能
StringBuffer c2vXmlStringBuffer = new StringBuffer("[{\"haspId\":\""+dogId+"\",\"c2v\":\""+burnC2v+"\"}]");
String c2vXmlString = bufferToSpecialString(c2vXmlStringBuffer);
String burnnerData = "c2v=" + c2vXmlString + "&ET="+URLEncoder.encode(ET, "UTF-8");
String burnRep = postRequestApi(new URL(reqIP+"ems/burner.html?pkId="+pkId+"&lineItemId="+lineItemId+"&action=burn&isJSON=true"),burnnerData,false,2);
if(burnRep.length()>0){
//step18:回收c2v,调用v2c
JSONArray burnArray = new JSONArray(burnRep);
JSONObject burnObject = burnArray.getJSONObject(0);
String burnV2cData = burnObject.getString("v2c");
postRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/v2c"),burnV2cData,false,2);
}
//step19:烧制加密狗后关闭链路
String blinkOffData = "<blink>OFF</blink>";
postRequestApi(new URL(reqEmsIP+"sentinel/ldk/v1/26157/keys/"+dogId+"/blink"),blinkOffData,false,0);
if("".equals(burnRep)||burnRep.length()<1|| "null".equals(burnRep)){
System.out.println("烧制加密狗失败!");
System.gc();
System.exit(0);
}else {
System.out.println("烧制加密狗成功!");
}
System.out.println("开始加密加密狗,请按如下指示操作!");
Encrypt crypt=new Encrypt();
crypt.encrypt();
}
对特殊的buffer字符串进行处理
对一些特定参数转换,注意
:java中"\
“用四个”\
"来表示,utf-8中的空格用20%来表示,对于?
、[
、{
、+
等特殊字符需要\\
来转义
/**
* 对特殊的buffer字符串进行处理
*
* @param stringBuffer 字符串缓冲区
* @return {@link String }
* @author yangz
* @date 2023/04/12
*/
public static String bufferToSpecialString(StringBuffer stringBuffer){
String str = stringBuffer.toString()
.replaceAll(" ", "%20")
.replaceAll("\\\\", "%5C")
.replaceAll("/", "%2F")
.replaceAll("\\?", "%3F")
.replaceAll("\"", "%22")
.replaceAll(":", "%3A")
.replaceAll("\\[", "%5B")
.replaceAll("]", "%5D")
.replaceAll("\\{", "%7B")
.replaceAll("}", "%7D")
.replaceAll("<", "%3C")
.replaceAll(">", "%3E")
.replaceAll("\\+", "%2B")
.replaceAll("=", "%3D")
.replaceAll("\r", "%5Cr")
.replaceAll("\n", "%5Cn")
.replaceAll("\t", "%5Ct");
return str;
}
get请求api
/**
* get请求api
*
* @param url url
* @param vendorId 供应商id
* @return {@link String }
* @author yangz
* @date 2023/04/12
*/
public static String getRequestApi(URL url, int vendorId) throws IOException{
HttpURLConnection cons = (HttpURLConnection) url.openConnection();
String now_cookie = COOKIES;
if(vendorId>0){
now_cookie += "vendorId="+vendorId;
}
cons.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36");
if(!"".equals(now_cookie)){
cons.setRequestProperty("cookie", now_cookie);
cons.setRequestProperty("ET", ET);
}
cons.setRequestProperty("referer", req80);
cons.setRequestProperty("X-Requested-With", "XMLHttpRequest, EMS");
if (url.getPort()==1947) {
cons.setRequestProperty("Host", reqHostEmsIP);
}else{
cons.setRequestProperty("Host", reqHostIP);
}
cons.connect();
int responseCode = cons.getResponseCode();
String response;
if (responseCode == HttpURLConnection.HTTP_OK) {
response = readFromStream(cons.getInputStream());
} else {
response = String.valueOf(responseCode);
}
cons.disconnect();
return response;
}
从流中读取数据
请求后有的是返回流数据,需要使用InputStream的read方法获取流中的数据
/**
* 从流中读取数据
*
* @param inputStream 输入流
* @return {@link String }
* @author yangz
* @date 2023/04/12
*/
public static String readFromStream(java.io.InputStream inputStream) throws java.io.IOException {
byte[] buffer = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(buffer)) != -1) {
sb.append(new String(buffer, 0, len, "UTF-8"));
}
return sb.toString();
}
post请求api
踩坑记录
:有些请求头这里设置了会冲突乱码之类的。比如Accept属性,Accept属性是用来告诉服务器客户端可以接受的响应类型(MIME 类型)及相应的优先级。如果你设置了Content-Type属性,再设置Accept属性则会乱码。所以只设置Content-Type属性即可
/**
* post请求api
*
* @param url url
* @param data 数据
* @param isLogin 是否为登录
* @param vendorId 供应商id
* @return {@link String }
* @author yangz
* @date 2023/04/12
*/
public static String postRequestApi(URL url,String data,boolean isLogin,int vendorId)throws IOException{
HttpURLConnection cons = (HttpURLConnection) url.openConnection();
if(isLogin){
cons.setInstanceFollowRedirects(false);
}
// 设置请求方法
cons.setRequestMethod("POST");
String now_cookie = COOKIES;
if(vendorId>0){
now_cookie += "; vendorId="+vendorId;
}
// 设置请求头
cons.setRequestProperty("Connection", "keep-alive");
cons.setRequestProperty("Referer", reqIP);
cons.setRequestProperty("Content-Length", String.valueOf(data.length()));
cons.setRequestProperty("sec-ch-ua-platform", "Windows");
cons.setRequestProperty("Sec-Fetch-Dest", "empty");
cons.setRequestProperty("Sec-Fetch-Mode", "cors");
cons.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36");
cons.setRequestProperty("Referrer-Policy", "strict-origin");
if(data.contains("blink")){
cons.setRequestProperty("Sec-Fetch-Site", "cross-site");
cons.setRequestProperty("Content-Type", "text/xml");
}else{
cons.setRequestProperty("Cookie", now_cookie);
cons.setRequestProperty("Sec-Fetch-Site", "same-origin");
cons.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
cons.setRequestProperty("ET", ET);
cons.setRequestProperty("sec-ch-ua", "\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"");
cons.setRequestProperty("X-Requested-With", "XMLHttpRequest, EMS");
}
// 开启输出流
cons.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(cons.getOutputStream());
wr.writeBytes(data);
wr.flush();
wr.close();
// read response
/*int responseCode = cons.getResponseCode();
System.out.println(responseCode);*/
BufferedReader in = new BufferedReader(new InputStreamReader(cons.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//判断是否为登录接口
if(isLogin){
// 获取HTTP响应的头信息
Map<String, List<String>> headers = cons.getHeaderFields();
// 获取Set-Cookie属性值
List<String> cookieList = headers.get("Set-Cookie");
if (cookieList != null) {
for (String cookie : cookieList) {
// 查找JSESSIONID属性
if (cookie.startsWith("JSESSIONID=")) {
String jsessionId = cookie.split(";")[0];
JSESSIONID = jsessionId.split("=")[1];
ET = jsessionId.split("=")[1];
}
}
}
if (!"".equals(JSESSIONID)) {
// 构建重定向的目标URL
String redirectUrl = reqIP+"ems/homePage.html?siteLanguage=en_US&ET=" + JSESSIONID;
// 设置重定向响应头
cons.disconnect();
cons = (HttpURLConnection) new URL(redirectUrl).openConnection();
COOKIES = "siteLanguage=en; JSESSIONID="+JSESSIONID+"; siteLanguage=en; loginInfo=ISV";
cons.setRequestProperty("Cookie", COOKIES);
cons.connect();
}
}
return response.toString();
}
结果如下:
之前写入过license,输入1
即重新烧制加密狗
结束语:所有的痛苦都是上天给予的成长提示