当前位置: 首页 > news >正文

网站开发中的api指什么i织梦cms网站

网站开发中的api指什么i,织梦cms网站,网站显示域名,海南省海口市龙华区jar包加密方案xjar, 不支持springboot3。这个发个魔改文章希望大家支持 最近公司需要将项目部署在第三方服务器#xff0c;于是就有了jar包加密的需求#xff0c;了解了下目前加密方案现况如下: 混淆方案#xff0c;就是在代码中添加大量伪代码#xff0c;以便隐藏业务代…jar包加密方案xjar, 不支持springboot3。这个发个魔改文章希望大家支持 最近公司需要将项目部署在第三方服务器于是就有了jar包加密的需求了解了下目前加密方案现况如下: 混淆方案就是在代码中添加大量伪代码以便隐藏业务代码加密方案将jar包中的所有class加密在运行时通过自定义classloader进行解密 目前有的所有加密方案基本思路都跟上面大差不差在了解了一圈决定使用了xjar这个开源项目。它的实现思路就是方案2. 打开github首页xjar项目文档还是不错的clone下来跟着文档上手很容易就测试并通过了我的测试项目接着便推给其他同事使用了。 好景不长下午就有同事找我说他的项目加密后不能成功运行。我去看了下加密操作上没什么问题但是就是加密包不能成功运行。 报错如下 错误: 找不到或无法加载主类 null 原因: java.lang.ClassNotFoundException: null panic: exit status 1了解了下同事那边使用了springboot3而我测试项目是springboot2。 难道不支持springboot3? 我心里想到。 先简单看了下加密的jar包目录结构很容易就发现以下问题 jar包中MANIFEST.MF文件中, Main-Class属性没有值jar包中没有将加解密相关的的class打进去 看样子需要进行二开了唉。 clone项目到本地拉个新分支。 首先看下源码在XBootEncryptor中定义了springboot的classloaderfinal String jarLauncher org.springframework.boot.loader.JarLauncher; 这里的jarlauncher在spring3中已经变包路径了。 没想到这么简单心里暗喜。于是把这里修改为org.springframework.boot.loader.launch.JarLauncher。 用spring3搭个demo, 重新打包。 再看jar文件 main-class已经写出去了xjar相关的包也成功写到jar包。松了口气看样子没太大问题。 开命令窗口启动项目一气呵成。看到终端输出springboot的logo时心里已经松了口气。 可惜天不遂愿又打印了几行日志后抛出以下错误 2024-09-27T17:51:36.40308:00 ERROR 3796 --- [demo] [ main] o.s.boot.SpringApplication : Application run failedorg.springframework.beans.factory.BeanDefinitionStoreException: Incompatible class format in URL [jar:nested:/D:/workspace/xiudianer/workspace/transport-mqtt-device-v4/branches/4.0.0/transport-mqtt-device-xjar/src/main/java/com/xd/device/ad/jars/encrypted5.jar/!BOOT-INF/classes/!/com/example/demo/DemoApplication.class]: set system property spring.classformat.ignore to true if you mean to ignore such files during classpath scanningat org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:504) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:351) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:277) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:306) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:246) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:165) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:417) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:789) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:607) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.4.jar!/:3.3.4]at com.example.demo.DemoApplication.main(DemoApplication.java:11) ~[!/:0.0.1-SNAPSHOT]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[encrypted5.jar:0.0.1-SNAPSHOT]at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[encrypted5.jar:0.0.1-SNAPSHOT]at io.xjar.boot.XJarLauncher.launch(XJarLauncher.java:27) ~[encrypted5.jar:0.0.1-SNAPSHOT]at io.xjar.boot.XJarLauncher.main(XJarLauncher.java:23) ~[encrypted5.jar:0.0.1-SNAPSHOT] Caused by: org.springframework.core.type.classreading.ClassFormatException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that is not supported yet. Consider compiling with a lower -target or upgrade your framework version. Affected class: URL [jar:nested:/D:/workspace/xiudianer/workspace/transport-mqtt-device-v4/branches/4.0.0/transport-mqtt-device-xjar/src/main/java/com/xd/device/ad/jars/encrypted5.jar/!BOOT-INF/classes/!/com/example/demo/DemoApplication.class]at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:59) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.SimpleMetadataReader.init(SimpleMetadataReader.java:48) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:122) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:470) ~[spring-context-6.1.13.jar!/:6.1.13]... 28 common frames omitted Caused by: java.lang.IllegalArgumentException: nullat org.springframework.asm.ClassReader.init(ClassReader.java:262) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.asm.ClassReader.init(ClassReader.java:180) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.asm.ClassReader.init(ClassReader.java:166) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.asm.ClassReader.init(ClassReader.java:287) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:56) ~[spring-core-6.1.13.jar!/:6.1.13]... 32 common frames omittedpanic: exit status 1 一脸蒙蔽这tm是什么错啊。 再看源码xjar是自定义classloader来加载并解密类核心就在XBootClassLoader.findClass。 这里源码中修改并打印下class的文件数据看看究竟加载的什么鬼~ 启动项目发现class文件已解密但为啥报错呢只能使用万能断点大法了在异常堆栈SimpleMetadataReader.getClassReader处断点从这里入手。 该方法反编译源码如下 private static ClassReader getClassReader(Resource resource) throws IOException {InputStream is resource.getInputStream();ClassReader var2;try {try {var2 new ClassReader(is);} catch (IllegalArgumentException var5) {throw new ClassFormatException(ASM ClassReader failed to parse class file - probably due to a new Java class file version that is not supported yet. Consider compiling with a lower -target or upgrade your framework version. Affected class: resource, var5);}} catch (Throwable var6) {if (is ! null) {try {is.close();} catch (Throwable var4) {var6.addSuppressed(var4);}}throw var6;}if (is ! null) {is.close();}return var2;} 这里有看到inputstrem,于是断点把inputstream打印输出看下内容发现这里读取的class文件居然是加密的。那么为啥这里没解密呢 继续往上跟堆栈。 根据参数Resource, 往上跟可以找到springboot扫描注解组件逻辑也就是扫描项目中所有有注解的class然后再调用这个方法读取加载class。 继续去看看这个Resource是怎么创建的。 一路跟在PathMatchingResourcePatternResolver.doFindPathMatchingJarResources发现了创建Resource资源的代码result.add(rootDirResource.createRelative(relativePath)); protected SetResource doFindPathMatchingJarResources(Resource rootDirResource, URL rootDirUrl, String subPattern) throws IOException {URLConnection con rootDirUrl.openConnection();JarFile jarFile;String jarFileUrl;String rootEntryPath;boolean closeJarFile;if (con instanceof JarURLConnection jarCon) {jarFile jarCon.getJarFile();jarFileUrl jarCon.getJarFileURL().toExternalForm();JarEntry jarEntry jarCon.getJarEntry();rootEntryPath jarEntry ! null ? jarEntry.getName() : ;closeJarFile !jarCon.getUseCaches();} else {String urlFile rootDirUrl.getFile();try {int separatorIndex urlFile.indexOf(*/);if (separatorIndex -1) {separatorIndex urlFile.indexOf(!/);}if (separatorIndex ! -1) {jarFileUrl urlFile.substring(0, separatorIndex);rootEntryPath urlFile.substring(separatorIndex 2);jarFile this.getJarFile(jarFileUrl);} else {jarFile new JarFile(urlFile);jarFileUrl urlFile;rootEntryPath ;}closeJarFile true;} catch (ZipException var17) {if (logger.isDebugEnabled()) {logger.debug(Skipping invalid jar class path entry [ urlFile ]);}return Collections.emptySet();}}try {if (logger.isTraceEnabled()) {logger.trace(Looking for matching resources in jar file [ jarFileUrl ]);}if (StringUtils.hasLength(rootEntryPath) !rootEntryPath.endsWith(/)) {rootEntryPath rootEntryPath /;}SetResource result new LinkedHashSet(64);EnumerationJarEntry entries jarFile.entries();while(entries.hasMoreElements()) {JarEntry entry (JarEntry)entries.nextElement();String entryPath entry.getName();if (entryPath.startsWith(rootEntryPath)) {String relativePath entryPath.substring(rootEntryPath.length());if (this.getPathMatcher().match(subPattern, relativePath)) {result.add(rootDirResource.createRelative(relativePath)); // 注意这里创建了resource资源}}}LinkedHashSet var22 result;return var22;} finally {if (closeJarFile) {jarFile.close();}}}上面的代码创建了resource资源于是继续跟进继续跟进createRelative方法那么问题来了为啥springboot2没问题spring3读取出来的却又是加密的这是为毛 最简单的方法就是对比着看 两个版本方法如下: springboot3 protected URL createRelativeURL(String relativePath) throws MalformedURLException {if (relativePath.startsWith(/)) {relativePath relativePath.substring(1);}return ResourceUtils.toRelativeURL(this.url, relativePath);}springboot2 Overridepublic Resource createRelative(String relativePath) throws MalformedURLException {if (relativePath.startsWith(/)) {relativePath relativePath.substring(1);}return new UrlResource(new URL(this.url, relativePath));} 上边代码一眼看也没太大问题。都是通过url创建了一个资源链接而已为毛就是跑步起来呢。 再次祭出断点大法。 断点后发现两个创建的资源中, URL 属性中的URLStreamHandler有很大区别。springboot2中该属性为xjar的解密器二springboot3中却是一个简单的文件读取器。 为啥呢喔翻了下源码发现在springboot2中创建Resouces实例时url属性实例是直接new出来的当前类的解密器也就是this.url中URLStreamHandler将会在URL的构造器中得到继承所以新Resource读取时也就会解密了 但在springboot3中ResourceUtils.toRelativeURL方法中创建URL时是先构建URI实例再创建URL实例这个过程中把this.URLStreamHandler丢失了。 原因找到了看了下springboot github的issue官方确实变更了原因是因为springboot2中的URL的构造函数在之后的jdk20标记为废弃所以就改了实现方法。不过官方表示下个版本会兼容处理这个问题目前spring3最新版为3.3.4 但问题是我们现在就要用啊只能拉个分支魔改了。 想想思路既然旧版本没问题那么喔先把spring-core包中的这个方法还原为老版本看看spring能正常跑起来不。测试了下没问题。 其实这里基本就没问题了实际项目中只要把这个spring-core包从私仓中替换项目加密也就没有太大的毛病但是这样对于追求完美的我来说方便性还差点。毕竟如果使用了springboot3的多个版本不可能每个都去修改替换下啊想想都好麻烦 那就再扩展下吧既然自定义了classloader那我可以在类加载过程中通过asm修改加载中的该方法的字节码将UrlResource.createRelative方法逻辑替换为老版本。 由于asm是通过字节码来修改方法的根据java源码来写出字节码小弟还没有那个功力。 取个巧直接使用javap -verbose URLResource.class 来查看老版本这个方法的指令流程 public org.springframework.core.io.Resource createRelative(java.lang.String) throws java.net.MalformedURLException;descriptor: (Ljava/lang/String;)Lorg/springframework/core/io/Resource;flags: (0x0001) ACC_PUBLICCode:stack6, locals2, args_size20: aload_11: ldc #36 // String /3: invokevirtual #37 // Method java/lang/String.startsWith:(Ljava/lang/String;)Z6: ifeq 159: aload_110: iconst_111: invokevirtual #38 // Method java/lang/String.substring:(I)Ljava/lang/String;14: astore_115: new #39 // class org/springframework/core/io/UrlResource18: dup19: new #13 // class java/net/URL22: dup23: aload_024: getfield #6 // Field url:Ljava/net/URL;27: aload_128: invokespecial #40 // Method java/net/URL.init:(Ljava/net/URL;Ljava/lang/String;)V31: invokespecial #41 // Method init:(Ljava/net/URL;)V34: areturnLineNumberTable:line 238: 0line 239: 9line 241: 15LocalVariableTable:Start Length Slot Name Signature0 35 0 this Lorg/springframework/core/io/UrlResource;0 35 1 relativePath Ljava/lang/String;StackMapTable: number_of_entries 1frame_type 15 /* same */Exceptions:throws java.net.MalformedURLException然后使用asm转译下以下为实现核心代码: Overridepublic MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {MethodVisitor mv super.visitMethod(access, name, desc, signature, exceptions);if (name.equals(createRelative) desc.equals((Ljava/lang/String;)Lorg/springframework/core/io/Resource;)) {// 修改原方法的字节码mv new MyMethodVisitor(mv) ;}return mv;}//MyMethodVisitor的结构public class MyMethodVisitor extends MethodVisitor {private final MethodVisitor target;public MyMethodVisitor(MethodVisitor mv) {super(ASM9, null);this.target mv;}//此方法在目标方法调用之前调用所以前置操作可以在这处理Overridepublic void visitCode() {target.visitCode();target.visitCode();target.visitVarInsn(ALOAD, 1);Label A new Label();Label B new Label();target.visitLdcInsn(/);target.visitMethodInsn(INVOKEVIRTUAL, java/lang/String, startsWith, (Ljava/lang/String;)Z, false);target.visitJumpInsn(IFEQ, A);target.visitVarInsn(ALOAD, 1);target.visitInsn(ICONST_1);target.visitMethodInsn(INVOKEVIRTUAL, java/lang/String, substring, (I)Ljava/lang/String;, false);target.visitVarInsn(ASTORE, 1);target.visitJumpInsn(GOTO,B);target.visitLabel(A);target.visitLabel(B);target.visitTypeInsn(Opcodes.NEW, org/springframework/core/io/UrlResource);target.visitInsn(DUP);target.visitTypeInsn(Opcodes.NEW, java/net/URL);target.visitInsn(DUP);target.visitVarInsn(ALOAD, 0);target.visitFieldInsn(GETFIELD, org/springframework/core/io/UrlResource, url, Ljava/net/URL;);target.visitVarInsn(ALOAD, 1);target.visitMethodInsn(INVOKESPECIAL, java/net/URL, init, (Ljava/net/URL;Ljava/lang/String;)V, false);target.visitMethodInsn(INVOKESPECIAL, org/springframework/core/io/UrlResource, init, (Ljava/net/URL;)V, false);target.visitInsn(ARETURN); //target.visitMaxs(6, 2);target.visitEnd();}Overridepublic void visitMaxs(int maxStack, int maxLocals) {super.visitMaxs(maxStack 1, maxLocals);}}最后由于classloader中使用了asm所以也需要将asm提前打到加密jar包 中。 然后再来编译一个加密包再启动成功 这样道友们就可以直接使用项目不必去修改spring-core包了。 项目传送地址https://github.com/MisterChangRay/xjar4springboot3 这个只支持springboot3哟~ 好用点个赞。把
http://www.hkea.cn/news/14564341/

相关文章:

  • 通化市住房和城乡建设局网站建设银行个人网银登录
  • 饰品公司网站建设方案广告设计专业有哪些
  • 网站登录注册页面模板下载传媒公司运营是干嘛的
  • 学校网站做几级等保山东省建设厅网站首页
  • 网站布局方法app网站怎么制作
  • 网站落地页怎么做股权分配系统建设网站
  • 南京哪些公司做网站软文推送
  • 沈阳网站建设思路网站手机访问 动易
  • 哪家公司制作网站wordpress更换文章背景色
  • 汕头企业建站中国城乡住房建设部网站
  • 网站建设与维护论文wordpress 多人编辑器
  • 网站开发php支付接口网站对图片优化吗
  • 手机大型网站服务器有了网站怎么做
  • 重庆綦江网站制作公司推荐长春建设网站
  • 织梦做双语网站著名的wordpress主题
  • 旅游包车网站最新模板百度知道个人中心
  • 内网网站建设的必要性做旅游海报的软件或是网站
  • 兰溪好品质高端网站设计指纹锁在什么网站做宣传好
  • 怎么在百度上搜到自己的网站红酒哪个网站做的好
  • 上海做响应式网站的公司天津建网站
  • 衡水网站建设联系电话如何能让网站尽快备案通过
  • 现在帮人做网站赚钱吗淮北论坛官网
  • 公司网站域名注册百度收录排名好的网站
  • 加上强机关网站建设管理的通知wordpress 手机无菜单
  • 毕业设计网站建设题目网络运维工程师简历怎么写
  • 网站关键词太多切实加强网站建设
  • 孝义网站开发公司做app和网站怎样
  • 福州免费自助建站模板怎么做百度seo网站
  • 无网站做百度推广做外贸主要看什么网站
  • 高端网站建设一般多少钱申请个人网站