使用Java模拟Web端的POST或GET请求,实现自动化操作:加密狗烧制技术详解

简介

硬件锁(加密狗)加密软件。与金雅特公司合作的方式是:买家公司开发一个授权程序(这里公司的授权程序: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即重新烧制加密狗
在这里插入图片描述

结束语:所有的痛苦都是上天给予的成长提示

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
模拟加密狗实现加密狗的软复制. 安装指南: 1. 解压RAR文件。 2. 确认已经安装了最新的圣天诺加密锁驱动程序。 3. 在运行EDGESPRO11.EXE来读锁和解析数据之前,确认LPT或USB端口上连接有硬件锁。 4. 选择“Sentinel”选项签,在“新建Dng文件”选项中点击“保存”,选择路径位置 来新建一个保存最终结果的dng文件。然后点击“读锁和解析数据”按钮。耗费的时 间取决于加密算法类型以及有多少单元需要解析算法。 “使用指定的Developer Id”和“使用指定的Write Password”是高级选项,并不是 必选项。 “使用指定的Developer Id”选项:允许对没有硬件锁的模拟器进行数据读取和解析。 “使用指定的Write Password”选项:如果你知道并在此处输入WP,整个解析会跳过 对WP的解析,以加快进度。 5. 读锁和解析完成后,程序会对得到的数据进行加密,并保存到之前指定的路径位置。 6. 运行SENTEMUL2007.exe,选择“Driver”选项签,并点击“安装仿真驱动”按钮, 如果安装成功,则下方的仿真驱动状态会显示为“driver is installed”。 7. 现在你需要打开“Emulator"”选项签,然后点击“启动仿真服务”按钮。如果一切 顺利,你会看到“SENTINEL Emulator Service is running”的信息。 8. 打开“Dongles”选项签,点击“加载dump文件”按钮,打开之前指定路径位置上由 EDGESPRO11.EXE创建的Dng文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热心码民阿振

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值