关于Java对接网络验证+实践小例子,简单易懂

一个简单的网络验证小例子,各位大佬勿喷

        突发奇想,如果一位A友找你拿一份 Working Fruits,但是你不想这位A友把你辛苦劳作、熬夜加点写出的代码分享他或她的另外一位朋友B友,也许并不是很有价值的一个小作业而已,但是就像我一样,多多少少有着私心的幼稚心理。这种想法就像你下载一个收费软件一样,所属权是你,需要授权码或者特定的方式得到你的允许,才能够运行整体代码。当然,不要破环人与人之间的关系或情感,学习为本(说笑了),教程只提供参考。 


目录

一. 预备知识点

二. 常见的网络验证   

三. 微验验证原理

四. 代码实现

五. 缺陷与优化


一. 预备知识点

        我们需要了解MD5和RC4加密原理。MD5是一种常用的哈希算法,它可以将任意长度的数据转换为固定长度的哈希值。通过对比哈希值,我们可以验证数据的完整性和一致性。而RC4是一种流密码算法,它可以根据密钥生成伪随机流,用于对数据进行加密和解密。通过使用MD5和RC4加密算法,我们可以确保在网络传输过程中的数据安全性。

        其次,我们需要了解Java反射。Java反射是一种强大的机制,它允许我们在运行时动态地获取类的信息并操作类的成员。在网络验证中,我们可以利用Java反射机制来动态加载和调用验证相关的类和方法(写好了就包装成一个JAR吧),从而实现灵活的验证逻辑。

        当然,网络验证的实现涉及到更多的知识和技术,比如数据库的构建和管理,有自己的服务器自己管理数据,自主随时管理数据,但是表数据的增删改查操作会产生更多的工作量。这些都是我们在实际开发中需要考虑的问题,需要具备相应的知识储备和技能因此,我们不如简单点,用别人写好的验证系统,直接拿来用不就是了,代码越简单越好对吧

        在实际的网络验证中,我们可以借助已有的对接API来实现本地的验证。这意味着我们可以选择市面上已有的验证服务或库,并通过网络接口进行数据传输和验证。通过使用这些对接API,我们可以简化验证的实现过程,提高开发效率。      

二. 常见的网络验证   

        在网络验证领域中,可以找到一些常见的验证案例,如T3、BS、易游、微验、大纸片等验证系统。这些系统各有特点,其中T3验证系统相对容易被破解,易游验证系统在外观上更加简单,但内部却更为复杂。考虑到教程的讲解需要,我们选择使用微验验证管理系统来进行讲解。

        微验验证管理系统以其独特的特点和功能而备受易语言开发者关注。它提供了一种简单而高效的验证解决方案,适用于各种场景和需求。通过微验验证管理系统,确保验证的安全性和可靠性。

        相比于其他验证系统,微验验证管理系统在设计上更加注重用户体验和易用性。它采用了简化的外观设计,使用户能够快速上手并进行验证操作。同时,微验验证管理系统内部的复杂性也为用户提供了更多的灵活性和定制化选项。

        本教程将重点介绍如何使用微验验证管理系统进行验证操作。通过详细的讲解和示例,本教程将帮助自身了解验证的基本原理和操作步骤。读者可以学习如何配置和管理微验验证系统,以及如何应用验证功能到项目中。

三. 微验验证原理

        先不管加密如何加密,解密如何解密,搞清楚这个验证流程,话不多说,看图。

四. 代码实现

        官方提供的Java对接例子只有不能就地运行、同时客户端不具有安卓特定的imei码,否则验证无法过签名,需要实际开发打包成APP才可使用,因此,我二改了官方提供的代码,可以就地运行。

        微验官方已经写好的rc4加密解密方法,可直接使用

        需要具体看懂吗,不需要,只需要明白每个方法的作用,具体怎么实现的不重要,我还是更喜欢面向对象

        RC4加密算法工具类详解

  1. encryRC4String方法:将给定的字符串数据使用RC4算法进行加密,并返回加密后的十六进制字符串形式。参数包括待加密的数据、密钥和字符集。

  2. encryRC4Byte方法:将给定的字符串数据使用RC4算法进行加密,并返回加密后的字节数组形式。参数包括待加密的数据、密钥和字符集。

  3. decryRC4方法:将给定的十六进制字符串数据使用RC4算法进行解密,并返回解密后的字符串形式。参数包括待解密的数据、密钥和字符集。

  4. initKey方法:根据给定的密钥生成RC4算法所需的初始密钥。返回一个字节数组。

  5. bytesToHex方法:将字节数组转换为十六进制字符串形式。返回转换后的字符串。

  6. hexToByte方法:将十六进制字符串转换为字节数组形式。返回转换后的字节数组。

  7. RC4Base方法:根据给定的输入数据和密钥使用RC4算法进行加密或解密操作。返回加密或解密后的字节数组。

     属性KEK 特定的密钥,不同的密钥产生不同的结果,不可更改

        RC4工具类 

import java.io.UnsupportedEncodingException;public class RC4Util {public static final String KEY = "PZ8KBd4TbE7mjEb";public RC4Util() {}public static String encryRC4String(String data, String key, String chartSet) throws UnsupportedEncodingException {return data != null && key != null ? bytesToHex(encryRC4Byte(data, key, chartSet)) : null;}public static byte[] encryRC4Byte(String data, String key, String chartSet) throws UnsupportedEncodingException {if (data != null && key != null) {byte[] bData;if (chartSet != null && !chartSet.isEmpty()) {bData = data.getBytes(chartSet);return RC4Base(bData, key);} else {bData = data.getBytes();return RC4Base(bData, key);}} else {return null;}}public static String decryRC4(String data, String key, String chartSet) throws UnsupportedEncodingException {return data != null && key != null ? new String(RC4Base(hexToByte(data), key), chartSet) : null;}private static byte[] initKey(String aKey) {byte[] bkey = aKey.getBytes();byte[] state = new byte[256];int index1;for(index1 = 0; index1 < 256; ++index1) {state[index1] = (byte)index1;}index1 = 0;int index2 = 0;if (bkey.length == 0) {return null;} else {for(int i = 0; i < 256; ++i) {index2 = (bkey[index1] & 255) + (state[i] & 255) + index2 & 255;byte tmp = state[i];state[i] = state[index2];state[index2] = tmp;index1 = (index1 + 1) % bkey.length;}return state;}}public static String bytesToHex(byte[] bytes) {StringBuffer sb = new StringBuffer();for(int i = 0; i < bytes.length; ++i) {String hex = Integer.toHexString(bytes[i] & 255);if (hex.length() < 2) {sb.append(0);}sb.append(hex);}return sb.toString();}public static byte[] hexToByte(String inHex) {int hexlen = inHex.length();byte[] result;if (hexlen % 2 == 1) {++hexlen;result = new byte[hexlen / 2];inHex = "0" + inHex;} else {result = new byte[hexlen / 2];}int j = 0;for(int i = 0; i < hexlen; i += 2) {result[j] = (byte)Integer.parseInt(inHex.substring(i, i + 2), 16);++j;}return result;}private static byte[] RC4Base(byte[] input, String mKkey) {int x = 0;int y = 0;byte[] key = initKey(mKkey);byte[] result = new byte[input.length];for(int i = 0; i < input.length; ++i) {x = x + 1 & 255;y = (key[x] & 255) + y & 255;byte tmp = key[x];key[x] = key[y];key[y] = tmp;int xorIndex = (key[x] & 255) + (key[y] & 255) & 255;result[i] = (byte)(input[i] ^ key[xorIndex]);}return result;}
}

        接下来是通过官方提供的加密工具类自主写的对接例子类,可以通过上文中的验证流程图共同参考。

        WeiYan对接类

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.Random;//TODO:Benmaopublic class WeiYan {String kami;//卡密public String markcode;//设备码public long time;//时间戳//Long time = System.currentTimeMillis()public String appKey="57012";//不可更改//"kami="+卡密+"&markcode="+设备码+"&t="+时间戳+"&"+sss.APPKEYpublic String data;public String SIGN;//通过md5加密public int random;//随机数,范围[1000, 9999]public String url="https://wy.llua.cn/api/?id=kmlogon"+"&app="+this.appKey+"&data=";//加密字段MD5public void Gm(String kami){this.kami=kami;this.time=System.currentTimeMillis()/1000;//Long.parseLong(String.valueOf(System.currentTimeMillis()).substring(0 ,10))this.markcode=getDeviceID();//getDeviceID();//需要加密的字段String str="kami="+this.kami+"&markcode="+this.markcode+"&t="+this.time+"&"+this.appKey;this.SIGN = stringToMD5(str);//encodeMD5(str);}//Rce4字段加密public void GD(){//随机数this.random=new Random().nextInt(99999)+1000;//范围1000~9999//需要加密的字段String str="kami="+this.kami+"&markcode="+this.markcode+"&t="+this.time+"&sign="+this.SIGN+"&value"+this.time+this.random;try {this.data=RC4Util.encryRC4String(str, RC4Util.KEY, "UTF-8");url+=this.data;} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}//返回数据解密public String deRec4(String anUrl){//String anUrl = "https://wy.llua.cn/api/?id=kmlogon&app=57012&data=4a5311e1cf22abb6c079de314f7f7ca9670658e0d306b87a9ab62f560e75ec31cdb0598abc2df00063003484e229ee81d0e07daf64b6d8a4cd190835bdf0c8bbd329b901888296a9a376c9bd73e62f56bce31982e072a38f8fb1fc261d43ce7231edf7c7a883bfec92c47475f0a07e3045161fcc10e5";URL url = null;String res ="";//最终结果try {url = new URL(anUrl);URLConnection conn = url.openConnection();BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));String inputLine;StringBuilder result = new StringBuilder();while ((inputLine = in.readLine()) != null) {result.append(inputLine);}//System.out.println(result);//加密前的字段res=result.toString();} catch (Exception e) {throw new RuntimeException(e);}//解码try {String json = RC4Util.decryRC4(res, RC4Util.KEY, "UTF-8");return json;} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}}//MD5加密public static String encodeMD5(String str){try{MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(str.getBytes("UTF-8"));byte messageDigest[] = md5.digest();StringBuilder hexString = new StringBuilder();for (byte b : messageDigest){hexString.append(String.format("%02X", b));}return hexString.toString().toLowerCase();}catch (Exception e){e.printStackTrace();}return "";}//iApp Md5加密public static String stringToMD5(String plainText){byte[] secretBytes = new byte[0];try {secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}String md5code = new BigInteger(1, secretBytes).toString(16);for(int i = 0; i < 32 - md5code.length(); i++){md5code = "0" + md5code;}return md5code;}//获取独立设备码public static String getDeviceID() {try {Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();while (networkInterfaces.hasMoreElements()) {NetworkInterface networkInterface = networkInterfaces.nextElement();byte[] mac = networkInterface.getHardwareAddress();if (mac != null) {StringBuilder sb = new StringBuilder();for (byte b : mac) {sb.append(String.format("%02X", b));}return sb.toString().toLowerCase();}}} catch (SocketException e) {e.printStackTrace();}return null;}
}

RC4加密算法工具类详解 

  1. Gm方法:对卡密进行加密处理,生成设备码和时间戳,并计算签名。参数为卡密。

  2. GD方法:对需要加密的字段进行RC4加密,并生成随机数。参数为卡密。

  3. deRec4方法:对返回的数据进行解密处理。参数为需要解密的URL。

  4. encodeMD5方法:对字符串进行MD5加密处理。参数为待加密的字符串。

  5. stringToMD5方法:对字符串进行MD5加密处理,并返回加密后的结果。参数为待加密的字符串。

  6. getDeviceID方法:获取设备的唯一标识码。

  7. kami(卡密)、markcode(设备码)、time(时间戳)、appKey(应用密钥)、data(加密后的数据)、SIGN(签名)、random(随机数)和url(请求的URL)。

    public String getKami() {return kami;}public void setKami(String kami) {this.kami = kami;}public String getMarkcode() {return markcode;}public void setMarkcode(String markcode) {this.markcode = markcode;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public String getAppKey() {return appKey;}public void setAppKey(String appKey) {this.appKey = appKey;}public String getData() {return data;}public void setData(String data) {this.data = data;}public String getSIGN() {return SIGN;}public void setSIGN(String SIGN) {this.SIGN = SIGN;}public int getRandom() {return random;}public void setRandom(int random) {this.random = random;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}

        接下来就是写一个验证例子。上述代码编译成一个jar包,然后使用反射调用其内部方法

         Main类

/*** @作者:笨猫* @create: 2024-03-16 14:52**/
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;public class main {public static void main(String[] args) {String kami = "Benmao2127FC";//这个就是卡密try {// 反射调用 WeiYan()构造方法,输出this.urlClass<?> weiYanClass = Class.forName("top.benmao.rc4.WeiYan");Constructor<?> weiYanConstructor = weiYanClass.getConstructor();Object weiYanObject = weiYanConstructor.newInstance();Method getUrlMethod = weiYanClass.getDeclaredMethod("getUrl");getUrlMethod.setAccessible(true);String url = (String) getUrlMethod.invoke(weiYanObject);System.out.println("this.url: " + url);// 反射调用Gm方法,并输出属性this.SIGNMethod gmMethod = weiYanClass.getDeclaredMethod("Gm", String.class);gmMethod.setAccessible(true);gmMethod.invoke(weiYanObject, kami);String sign = (String) weiYanClass.getField("SIGN").get(weiYanObject);System.out.println("this.SIGN: " + sign);// 反射调用GD方法,再次输出this.urlMethod gdMethod = weiYanClass.getDeclaredMethod("GD");gdMethod.setAccessible(true);gdMethod.invoke(weiYanObject);url = (String) getUrlMethod.invoke(weiYanObject);System.out.println("this.url: " + url);// 反射调用deRec4()方法,获取返回值并输出Method deRec4Method = weiYanClass.getDeclaredMethod("deRec4", String.class);deRec4Method.setAccessible(true);String result = (String) deRec4Method.invoke(weiYanObject, url);System.out.println("Result: " + result);} catch (Exception e) {e.printStackTrace();}}
}

        运行结果

        只需要把获取的结果JSON后进入校验即可,剩下的就看自己怎么运用吧。

五. 缺陷与优化

        想说的是,比起官方提供的代码,就地运行只需要懂一点点Java语言,有可能解密就只是一个变量的事情,如果需要更加安全、高效、易处理的工作方式,可以继续尝试包装成一个apk并选择各大官方的加固平台进行加固,如360加固。

        本次教程结束了,感兴趣的可以关注我,如有与本博客持有不同的看法或评判,请随时留意吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/282608.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【微服务】Feign远程调用

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;微服务 ⛺️稳中求进&#xff0c;晒太阳 先来看我们以前利用RestTemplate发起远程调用的代码&#xff1a; 存在下面的问题&#xff1a;代码可读性差&#xff0c;编程体验不统一参数复杂URL…

2016年认证杯SPSSPRO杯数学建模A题(第二阶段)洗衣机全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 A题 洗衣机 原题再现&#xff1a; 洗衣机是普及率极高的家用电器&#xff0c;它给人们的生活带来了很大的方便。家用洗衣机从工作方式来看&#xff0c;有波轮式、滚筒式、搅拌式等若干种类。在此基础上&#xff0c;各厂商也推出了多种具体方案…

详解如何使用Pytest进行自动化测试

为什么需要自动化测试 自动化测试有很多优点&#xff0c;但这里有3个主要的点 可重用性:不需要总是编写新的脚本&#xff0c;除非必要&#xff0c;即使是新的操作系统版本也不需要编写脚本。可靠性:人容易出错&#xff0c;机器不太可能。当运行不能跳过的重复步骤/测试时&…

【数据结构】——栈与队列(附加oj题详解)深度理解

栈 1.栈的定义 栈&#xff1a;栈是仅限与在表尾进行插入或者删除的线性表 我们把允许一端插入和删除的一端叫做栈顶&#xff0c;另一端叫栈底&#xff0c;不含任何元素的栈叫做空栈&#xff0c;栈又叫做后进先出的线性表&#xff0c;简称LIFO结构 2.栈的理解 对于定义里面…

【C++】狗屁不通文章生成器2.0

【C】狗屁不通文章生成器2.0 1 前言2 改进2.1 字词的前后关系2.2 文章生成系统 3 实现(部分)3.1 class wordpair3.1.1 转化为 json3.1.2 添加后缀词3.1.3 选择后缀词 3.2 class createArticle3.2.1文本分割3.2.2生成文章 4演示4.1 wordpair(3x2), 启动词(春天)4.2 wordpair(2x1…

C语言笔记:函数与程序结构

目录 ACM金牌带你零基础直达C语言精通-课程资料 一.作用域的基本概念 二.函数 1. 函数的定义和使用 2.为什么一定要有函数结构 3.形参与实参 4.函数的声明和定义 5.递归函数 此代码中递归函数执行流程&#xff1a; 练习&#xff1a;求斐波那契数列第n项的值&#xff1a; 欧几里…

CSDN个人简介优化 html font属性

CSDN个人简介优化 html font属性 个人简介个人简介优化字体21种样式选择字体大小设置4号字体 字体颜色设计渐变色&#xff08;可惜不能显示&#xff09; 字体加粗设置 <b>标签 个人简介 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光…

mysql查询条件包含IS NULL、IS NOT NULL、!=、like %* 、like %*%,不能使用索引查询,只能使用全表扫描,是真的吗???

不知道是啥原因也不知道啥时候, 江湖上流传着这么一个说法 mysql查询条件包含IS NULL、IS NOT NULL、!、like %* 、like %*%,不能使用索引查询&#xff0c;只能使用全表扫描。 刚入行时我也是这么认为的&#xff0c;还奉为真理&#xff01; 但是时间工作中你会发现还是走索引…

Games101Homework【0】Build an environment

Preface: I just want 放洋屁&#xff0c;and then learn graphics. So,This essay is born. I will show you the whole process of my study,Including the bugs I created. Cool lets begin! Download: BaiduNetworkDisk:from bilibili comment https://pan.baidu.com/…

Java后端八股-------并发编程

图中的 synchronized方法如果没有锁&#xff0c;那么可能会有超卖&#xff0c;数据错误等情况。 加锁之后会按顺序售卖。 synchronized的底层是monitor。 线程没有竞争关系的时候&#xff0c;引入了轻量级锁&#xff0c;当需要处理竞争关系的时候一定要用到重量级锁(线程的…

Java学习笔记(20)

可变参数 输入的参数数量不确定 底层就是把输入的参数放进一个数组里 只能写一个可变参数如果还有其他形参&#xff0c;可变参数要放在最后写 可变参数在底层就是一个数组 Collections Addall shuffle 练习 package exercise;import java.util.ArrayList; import java.util.C…

递增四元组

解法&#xff1a; 首先都可以想到dp[i]&#xff1a;第i个元素结尾的递增四元组有dp[i]个 然后发现有一组数据&#xff1a;2,3,6,1,5,8。会出现6结尾和5结尾的递增三元组&#xff0c;也就是未来的决策受过去影响&#xff0c;专业的说就是有后效性。需要强化约束条件&#xff0…

1.2 编译型语言和解释型语言的区别

编译型语言和解释型语言的区别 通过高级语言编写的源码&#xff0c;我们能够轻松理解&#xff0c;但对于计算机来说&#xff0c;它只认识二进制指令&#xff0c;源码就是天书&#xff0c;根本无法识别。源码要想执行&#xff0c;必须先转换成二进制指令。 所谓二进制指令&…

使用gimp制作头像

1.裁剪图像 &#xff08;1&#xff09;用GIMP打开图像。 &#xff08;2&#xff09;在工具箱中选中剪裁工具。 &#xff08;3&#xff09;在工具箱下边的工具选项中&#xff0c;勾选 固定→宽高比&#xff0c;并在下面的数值框中输入1:1。 &#xff08;4&#xff09;在图像中…

ginblog博客系统/golang+vue

ginblog博客系统 前台&#xff1a; 后台&#xff1a; Gitee的项目地址&#xff0c;点击进入下载 注意&#xff1a; 数据库文件导入在model里面&#xff0c;直接导入即可。 admin和front前后台系统记住修改https里的地址为自己的IP地址&#xff1a; front同上。

Springboot+vue的大学生选修选课系统的设计与实现(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的大学生选修选课系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;control…

显卡基础知识及元器件原理分析

显卡应该算是是目前最为火热的研发方向了&#xff0c;其中的明星公司当属英伟达。 当地时间8月23日&#xff0c;英伟达发布截至7月30日的2024财年第二财季财报&#xff0c;营收和利润成倍增长&#xff0c;均超市场预期。 财报显示&#xff0c;第二财季英伟达营收为135.07 亿美…

第十四届蓝桥杯JavaB组省赛真题 - 阶乘求和

/ 10^9考虑前九位&#xff0c;% 10^9保留后9位 解题思路: 求获取结果的后九位数字&#xff0c;需要对10^9取余&#xff0c;因为202320232023这个数字的阶乘太大&#xff0c;必须要减少计算量&#xff0c;因为当一个整数乘以10^9后对其取余&#xff0c;那么结果都为0。 所以我…

模拟B\S服务器(扩展知识点)

3.2 模拟B\S服务器(扩展知识点) 模拟网站服务器&#xff0c;使用浏览器访问自己编写的服务端程序&#xff0c;查看网页效果。 案例分析 准备页面数据&#xff0c;web文件夹。 复制到我们Module中&#xff0c;比如复制到day08中 我们模拟服务器端&#xff0c;ServerSocket类…

【C++ leetcode】双指针问题

1. 611. 有效三角形的个数 题目 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 题目链接 . - 力扣&#xff08;LeetCode&#xff09; 画图 和 文字 分析 判断是否是三角形要得到三边&#xff0c;由于遍历三边要套三层循环&#x…