xmldecoder,Java语言 有关xml文件写的过程中,出现异常导致文件为空的情况
xmldecoder,Java语言 有关xml文件写的过程中,出现异常导致文件为空的情况详细介绍
本文目录一览: xmldecoder反序列化漏洞分析
java提供了很多xml文档解析的类库,包括dom4j,domj,SAX等库,可以进行xml文档的解析,这些库的使用不当,会导致XXE漏洞的发生,但是这些类库中,SAX库允许自己去定义整个xml文档处理的handler,可以在xml文档解析的过程中,对解析出来的节点进行一些操作
而为java反序列化定义的handler,会导致一些java反序列化的问题的发生
poc:
获取到文件内容之后,用XMLDecoder解析,在下面调用了readObject方法
进入readObject方法中
这里对文档进行了解析,而XMLDecoder.this.handler其实就是
DocumentHandler
这个handler很重要,所有反序列化的操作都是在这个类中进行的
之类通过SAXParserFactory实例化了一个SAXParser的实例,并且调用了其中的parse方法
复现过java XXE漏洞的师傅应该看见过SAXParser的用法,它允许用户自己去定义处理文档的handler
可以看到,用户可以将自己定义的Handler,只要这个类继承了DefaultHandler,可以看一下官网的例子:
自己的Handler可以在解析的不同阶段,进行不同的操作,这个特点就让xml文档成为了可以进行java序列化的载体,DocumentHandler这个handler就是处理xml文档反序列化的
接下来,调用SAXParser对xml文档进行解析,在对一些属性的设置以后,真正的解析流程在XML11Configuration这个类中的parse方法中开始
首先是对实体的解析:
因为我们的文档中并没有xml实体,所以这一步不用关注
之后进行文档的解析
进入到scanDocument函数中
这里通过next函数,解析了文档,并且返回当前解析的状态,整个文档的具体解析过程在XMLDocumentFragmentScannerImpl这个类的ContentDriver类中,里面的解析过程很复杂,具体的解析过程不要过于关注,重点在解析出来的结果的处理上
当发现当前的文档为根节点的时候,调用fContentDriver的next方法,在这里进行ROOT节点的解析
一直到XMLDocumentFragmentScannerImpl的scanStartElement方法中
在之类对文档进行解析,调用scanName解析出来第一个节点名为:java
之后寻找java节点的结束字符在哪,并且解析出来中间的所有属性
在解析结束以后,会将这个节点中的所有属性添加到fAttributes中
最后来到startElement函数中,可以认为fElementQName就是我们的节点名称,fAttributes就是这个节点中所有属性组成的一个字典
最后调用到DocumentHandler的startElement才到真正反序列化的地方
到这里,一个节点的解析就算结束了,头都看大了,先附上一张调用栈,再到DocumentHandler中看具体的反序列化过程
在最后,调用了DocumentHandler.startElement函数,我们进入看一下
在这里会根据不同的节点实例化不同的节点Handler
this.handlers中寻找java节点对应的handler,可以看一下this.handlers里面所有的handler都是什么,它是一个HashMap,在属性中有定义 private final Map
<string, class
> handlers = new HashMap();
在构造方法中,对handlers进行了赋值
这也就是XMLDecoder所有支持的节点类型,不同的节点会调用不同的ElementHandler进行处理,我们的java节点,应该是被JavaElementHandler处理的
回到startElement的方法中
在实例化JavaElementHandler类以后,调用了setParent将上一次的handler保存,这一步相当于将每一个节点的处理类串成了一个链
这一步获取到所有的节点属性,并且调用处理handler自己实现的addAttribute方法,可以看一下JavaElementHandler的addAttribute
这里通过我们设置的class属性的内容,获取了对应的类,也就是java.beans.XMLDecoder类的class
之后调用对应handler的startElement,而java的handler没有操作,所以进行下一个节点的解析
下一个节点是object,具体解析流程就不再分析
object对应的Handler为ObjectElementHandler,可以发现,startElement中的重点其实就是每个Handler的addAttribute方法和startElement方法
调用父类的addAttribute方法
这一步获得了ProcessBuilder的class
处理handler:ArrayElementHandler
addAttribute:
这里定义了数组元素的类型和数组大小
startElement:
这里实例化了一个数组元素,并且返回了一个ValueObject对象
void节点比较特殊,void节点其实是object节点的一个子类,它本身没有定义什么方法
我们可以不用过多的关注void节点的处理规则,只需要理解它的作用就是声明一个变量就可以,可以这么理解:
在一个节点处理结束以后,会由内向外依次调用每个节点的endElement方法
比如我们的poc
在解析完touch的string节点的之后,触发string的endElement,主要就是将将值设置为StringElementHandler的属性
之后向ArrayElementHandler中的数组添加进去这个String,对每个element都会调用getValueObject方法,而其中
void节点的endElement很有意思
看一下getContextBean方法
这里会获取上一个Handler的ValueObject的值,而这个ValueObject的value就是我们在属性中定义的对象,void节点的上一个节点是array节点,我们在array节点中定义了一个大小为2的String数组,所以获取到的ValueObject就为这个数组
因为我们只设置了void的属性为index="0",所以会进入到var4=set的条件中
最后的Express类,相当于是对var3这个对象调用其中的var4的方法,参数为var2,这样,就为这个String数组赋值了第一个值为touch
来到第二个void标签
当来到
进入到getContextBean
在这里调用了parent的getValueObject方法,也就是object标签
获取了ObjectElementHandler中的ProcessBuilder对象
最后调用start执行命令
java.beans.xmlencoder 在什么包里面
就在java.beans包,包含XMLEncoder和XMLDecoder。
以下是引用片段:
package com.imct.util;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
*
提供保存和读取的方法
* @author 殷晋
*
清华大学汽车工程开发研究院@2005
* @version 1.0
* 2005-8-5 16:44:49
*/
public class ObjectToXMLUtil
{
/**
* 把java的可序列化的对象(实现Serializable接口)序列化保存到XML文件里面,如果想一次保存多个可序列化对象请用集合进行封装
* 保存时将会用现在的对象原来的XML文件内容
* @param obj 要序列化的可序列化的对象
* @param fileName 带完全的保存路径的文件名
* @throws FileNotFoundException 指定位置的文件不存在
* @throws IOException 输出时发生异常
* @throws Exception 其他运行时异常
*/
public static void objectXmlEncoder(Object obj,String fileName)
throws FileNotFoundException,IOException,Exception
{
//创建输出文件
File fo = new File(fileName);
//文件不存在,就创建该文件
if(!fo.exists())
{
//先创建文件的目录
String path = fileName.substring(0,fileName.lastIndexOf('.'));
File pFile = new File(path);
pFile.mkdirs();
}
//创建文件输出流
FileOutputStream fos = new FileOutputStream(fo);
//创建XML文件对象输出类实例
XMLEncoder encoder = new XMLEncoder(fos);
//对象序列化输出到XML文件
encoder.writeObject(obj);
encoder.flush();
//关闭序列化工具
encoder.close();
//关闭输出流
fos.close();
}
/**
* 读取由objSource指定的XML文件中的序列化保存的对象,返回的结果经过了List封装
* @param objSource 带全部文件路径的文件全名
* @return 由XML文件里面保存的对象构成的List列表(可能是一个或者多个的序列化保存的对象)
* @throws FileNotFoundException 指定的对象读取资源不存在
* @throws IOException 读取发生错误
* @throws Exception 其他运行时异常发生
*/
public static List objectXmlDecoder(String objSource)
throws FileNotFoundException,IOException,Exception
{
List objList = new ArrayList();
File fin = new File(objSource);
FileInputStream fis = new FileInputStream(fin);
XMLDecoder decoder = new XMLDecoder(fis);
Object obj = null;
try
{
while( (obj = decoder.readObject()) != null)
{
objList.add(obj);
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
}
fis.close();
decoder.close();
return objList;
}
}
补充:
/**
* 对象输到XML文件
* @param obj 待输出的对象
* @param outFileName 目标XML文件的文件名
* @return 返回输出XML文件的路径
* @throws FileNotFoundException
*/
public static String object2XML(Object obj,String outFileName)throws FileNotFoundException{
//构造输出XML文件的字节输出流
File outFile=new File(outFileName);
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(outFile));
XMLEncoder xmlEncoder=new XMLEncoder(bos);//构造一个XML编辑器
xmlEncoder.writeObject(obj);//使用XML编码器写对象
xmlEncoder.close();//关闭编码器
return outFile.getAbsolutePath();
}
/**
* 把XML文件解码成对象
* @param inFileName输入的XML文件
* @return 返回生成的对象
* @throws FileNotFoundException
*/
public static Object xml2Object(String inFileName)throws FileNotFoundException{
//构造输入的XML文件的字节输入流
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(inFileName));
XMLDecoder xmlDecoder=new XMLDecoder(bis);//构造一个XML解码器
Object obj=xmlDecoder.readObject();//使用XML解码器读对象
xmlDecoder.close();//关闭解码器
return obj;
}
请问java中怎么将生成的XML转化为字符串?
此方法传入文件名即可获得对象
-------------------------------------------
import java.beans.XMLDecoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
public class ReadXml {
public static Object getXml(String path){
File file=new File(path);
FileInputStream fileInputStream;
Object object=null;
try {
fileInputStream = new FileInputStream(file);
XMLDecoder decoder=new XMLDecoder(fileInputStream);
object=decoder.readObject();
fileInputStream.close();
decoder.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return object;
}
}
---------------------------------------------------------------------
如果不可以 用这个写的方式 直接写对象到XML里 此方法需传入对象和写入路径
mport java.beans.XMLEncoder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class WriteXml {
public static void setXml(Object o,String fileName){
File file=new File(fileName);
try {
FileOutputStream fileOutputStream=new FileOutputStream(file);
XMLEncoder encoder=new XMLEncoder(fileOutputStream);
encoder.writeObject(o);
encoder.flush();
encoder.close();
fileOutputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我想问一下你的Document是什么类型的?如果是org.dom4j.Document的话,你可以Document doc = ...;String str = doc.asXML();可以直接利用asXML()这个方法!其实的话就不清楚了!还得查下!
=========================
还是没有查到!好像org.w3c.dom不提供这个方法!也可能是我没弄对!在或者只能先存入文件,然后读取...囧~~
不过楼主为什么要用org.w3c.dom不用org.dom4j,一般说来现在比较公认dom4j是相对方便的!
我贴一段解析xml代码你参考下
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
public class Parsmx{
public static void main(String[] args){
try{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder buld = dbf.newDocumentBuilder();
Document doc = buld.parse(new File("smx.xml"));
Element root = doc.getDocumentElement();
System.out.println("根节点标记名 :"+root.getTagName());
System.out.println("*************下面遍历XML元素****************");
NodeList list2 = root.getElementsByTagName("title");
Element title22Element = (Element)list2.item(0);
String titie2 = title22Element.getFirstChild().getNodeValue();
System.out.println(titie2+":");
NodeList list = root.getElementsByTagName("man");
Element sssElement = (Element)list.item(0);
String sss = sssElement.getFirstChild().getNodeValue().trim();
System.out.println("sss"+sss+"sss");
for(int i=0;i < list.getLength();i++){
Element element = (Element)list.item(i);
String id = element.getAttribute("id");
NodeList nameList = element.getElementsByTagName("name");
Element titleElement = (Element)nameList.item(0);
String name = titleElement.getFirstChild().getNodeValue();
NodeList ageList = element.getElementsByTagName("age");
Element tElement = (Element)nameList.item(0);
String age = titleElement.getFirstChild().getNodeValue();
NodeList eList = element.getElementsByTagName("email");
Element tiElement = (Element)nameList.item(0);
String email = titleElement.getFirstChild().getNodeValue();
System.out.println("ID :" + id + " " + "name :" + name + " " + "age :" + age+" "+"email :"+email);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
javax.xml.parsers.DocumentBuilderFactory dbf;
javax.xml.parsers.DocumentBuilder db;
dbf = DocumentBuilderFactory.newInstance();
db = dbf.newDocumentBuilder();
org.w3c.dom.Document doc = db.parse(new FileInputStream(xxxx.xml));
org.w3c.dom.Element rootElement = doc.getDocumentElement();
org.w3c.dom.NodeList nodeList = rootElement.getElementsByTagName("your node");
org.w3c.dom.Node node = (Element) nodeList.item(0);
String s = node.getElementsByTagName("your node").item(0).getFirstChild();
String a="A4_5";
String b="A4";
if(a.indexOf(b)!=-1)
{
System.out.println("存在");
}
求助,用XMLDecoder读取对象出现数组越界异
try{
temp = (D)xmlDecoder.readObject())
}catch(Exception e){
break;
}
outList.add(temp);
}
java xml报文从客户端传到服务端解析的小程序
用webservice,传一个xml格式的字符串
建议使用Jboss
使用jdom,dom4j等进行解析,还有一个很强大的东西XStream都可以进行XML操作,至于传送,可以放在头部setHeder 如果是对象的话就更简单了使用XMLEncoder java自带的。
XMLEncoder 的实例代码如下:
public static String beanToXml(Object obj)
throws UnsupportedEncodingException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
XMLEncoder encoder = new XMLEncoder(bos);
encoder.writeObject(obj);
encoder.close();
return bos.toString("UTF-8");
}
public static Object XmlToBean(String xmlParam)
throws UnsupportedEncodingException, DocumentException {
ByteArrayInputStream ios = new ByteArrayInputStream(
xmlParam.getBytes("UTF-8"));
XMLDecoder decoder = new XMLDecoder(ios);
Object obj = decoder.readObject();
return obj;
}
哪位懂C#和java高手 帮个忙
需要返回的类型 是由T决定的 这样的话java该怎么写呢?比如:
T1 sif = a.ReadFile
(@"D:\t.xml"); (c# 语法)
---
public static T List
readFile(String name){
// ....
}
不要在<>里面放T。你直接在里面放Object,然后你在传入的时候定义Object的类型就好了。
import java.beans.XMLDecoder;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.util.ArrayList;import java.util.List; /** * 读取由fileName指定的XML文件中的序列化保存的对象,返回的结果放在list中 * @param fileName 是文件名 * @return 由XMl文件里面保存的对象构成的list列表 * @throws IOException IO流错误 * @throws Exception 其他错误 * @author cdlylyj * */public class JRead{ public static List ReadFile(String fileName) throws IOException{ List list=new ArrayList(); File file=new File(fileName); FileInputStream fis=new FileInputStream(file); XMLDecoder decoder=new XMLDecoder(fis); Object obj=null; try{ while((obj=decoder.readObject())!=null){ list.add(obj); } }catch(Exception e){ e.printStackTrace(); } fis.close();//关闭输入流 decoder.close(); return list; }}
Java中object和xml互相转换
实例讲解了 将JavaBean转成xml字符串,将xml字符串反转成JavaBean
【下载实例】
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Object2XML {
public static String object2XML(Object obj, String outFileName)
throws FileNotFoundException {
// 构造输出XML文件的字节输出流
File outFile = new File(outFileName);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(outFile));
// 构造一个XML编码器
XMLEncoder xmlEncoder = new XMLEncoder(bos);
// 使用XML编码器写对象
xmlEncoder.writeObject(obj);
// 关闭编码器
xmlEncoder.close();
return outFile.getAbsolutePath();
}
public static Object xml2Object(String inFileName)
throws FileNotFoundException {
// 构造输入的XML文件的字节输入流
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(inFileName));
// 构造一个XML解码器
XMLDecoder xmlDecoder = new XMLDecoder(bis);
// 使用XML解码器读对象
Object obj = xmlDecoder.readObject();
// 关闭解码器
xmlDecoder.close();
return obj;
}
public static void main(String[] args) throws IOException {
// 构造一个StudentBean对象
StudentBean student = new StudentBean();
student.setName("wamgwu");
student.setGender("male");
student.setAge(15);
student.setPhone("55556666");
// 将StudentBean对象写到XML文件
String fileName = "AStudent.xml";
Object2XML.object2XML(student, fileName);
// 从XML文件读StudentBean对象
StudentBean aStudent = (StudentBean)Object2XML.xml2Object(fileName);
// 输出读到的对象
System.out.println(aStudent.toString());
}
}
Java语言 有关xml文件写的过程中,出现异常导致文件为空的情况
其实你应该在程序中构建一个模型和文件内容相对应,就好修改了。
如读取文件,构建模型,修改模型,写入文件。
import java.beans.XMLDecoder;import java.beans.XMLEncoder;import java.io.*;import java.util.ArrayList;import java.util.List;public class Main { public static void main(String[] args) { User user = new User("admin", "111111", new Adress("New York")); addUser(user); catXmlFile(); updatePassword("admin", "123456"); catXmlFile(); } public static boolean addUser(User user) { List
users = loadXmlForUsers(); for (User user1 : users) { if (user1.getUsername().equals(user)) { return false; } } users.add(user); writeXmlForUser(users); return true; } public static void updatePassword(String username, String password) { List
users = loadXmlForUsers(); for (User user : users) { if (user.getUsername().equals(username)) { user.setPassword(password); } } writeXmlForUser(users); } public static void catXmlFile() { try { System.out.println("=============="); BufferedReader br = new BufferedReader(new FileReader("users.xml")); while (br.ready()) { System.out.println(br.readLine()); } br.close(); } catch (IOException e) { e.printStackTrace(); } } public static void writeXmlForUser(List
users) { try { XMLEncoder encoder = new XMLEncoder(new FileOutputStream("users.xml")); encoder.writeObject(users); encoder.flush(); encoder.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static List
loadXmlForUsers() { List
users; try { XMLDecoder decoder = new XMLDecoder(new FileInputStream("users.xml")); users = (List
) decoder.readObject(); decoder.close(); } catch (Exception e) { users = new ArrayList<>(); } return users; } public static class User { private String username; private String password; private Adress adress; public User() { } public User(String username, String password, Adress adress) { this.username = username; this.password = password; this.adress = adress; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Adress getAdress() { return adress; } public void setAdress(Adress adress) { this.adress = adress; } } public static class Adress { private String name; public Adress() { } public Adress(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }}
dhtmlxtree如何关联数据库(请详解,解决问题后再追加50-100分)
dhtmlxtree只能从xml读取
如果想从数据库表中获取数据,该如何来做? 这问题回答好得写上几百页吧。找本书从头看一遍。
你可以这样 从数据库里读取结果集 然后看看java api里的java.beans.XMLEncoder和XMLDecoder类 将结果集序列化到xml文件 然后导入到dhtmlxtree中
ArrayList数组越界问题。。。急!!!
第三个对象读取存入以后继续读第4个对象的时候(XML里只有3个对象)报错 你这不是都明白了么
while(true){ //-------------43行----------------
try{
temp = (D)xmlDecoder.readObject())
}catch(Exception e){
break;
}
outList.add(temp);
}