ItextPdf 数字签名,HTML转PDF功能

来源:互联网 发布:gtaol美女捏脸数据 编辑:程序博客网 时间:2024/06/03 22:50
摘要: ItextPdf实现 数字签名,HTML转PDF功能

 哼哼,完成这篇,这周的任务算是完成了,上篇文章主要生成了自己的证书与和密码,这篇主要实现数字签名及HTML转成PDF功能。

  今天下午把功能基本完成了,常帅走过来说,你知道签名的解签的原理吗?尼玛...不清楚,cer,crt,pfx,csr..一大堆名称,看过转身就忘记了。。

  在弄功能时有几个细节,调试了半天,第一个是将不标准的HTML转成标准的HTML格式(就是必须是有始有终),不然itextpdf转不了,报错。 第二个是印章定位的问题,最后经过一遍遍调试,终于能将图在指定的位置显示了。

  主要功能如下

     1,将HTML转成PDF

     2,对此PDF进行签名

     3,打印签名。

   一,HContent.java 常量类,定义图片资源的位置   

package com.wowoyoo.helper;/** * @author hubs  * @version 创建时间:2017年3月22日 下午3:34:56 * 类说明 */public class Content {public static String BASE   = "/home/hubs/桌面/ssl/ok/";//文件存放路径/** The resulting PDF */public static String PDF_NEW  = BASE + "/test1.pdf"; // 创建的PDF/** The resulting PDF */public static String PDF_SIGNED   = BASE + "/signature_1.pdf"; // 签名的文件/** Info after verification of a signed PDF */public static String PDF_VERIFICATION= BASE + "verify.txt"; // 签证的信息,如果已更改,则值为空public static final String PFX_PATH = BASE + "client.pfx";// 证书,包含密钥public static final String PFX_PASS = "xxxxx"; // 这是签名的密码public static final String STAMP_PATH = BASE + "test.gif"; // 签名的图public static final String LOGO_PATH = BASE + "logo.png"; // 签名的图public static final String CER_PATH = BASE + "client.crt"; // 解答的证书,公钥public static byte[] OPEN_PASSWORD    = "hello".getBytes(); // 密码public static final String HTML_PATH   = BASE + "test.html";public static final String WORD_PATH   = BASE + "word.doc";}

    二,HTML转PDF类

package com.wowoyoo.helper;import java.io.ByteArrayInputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.nio.charset.Charset;import org.jsoup.Jsoup;import com.itextpdf.text.Document;import com.itextpdf.text.DocumentException;import com.itextpdf.text.PageSize;import com.itextpdf.text.pdf.PdfWriter;import com.itextpdf.tool.xml.XMLWorkerHelper;/** * @author hubs * @version 创建时间:2017年3月22日 下午3:29:21  *  类说明"HTML转PDF */public class HtmlToPdf {public static void createPdf(String HTML,String outFileName) throws IOException,DocumentException {Document document = new Document(PageSize.A4);PdfWriter pdfWriter = PdfWriter.getInstance(document,new FileOutputStream(outFileName));document.open();document.addAuthor("蜗蜗游旅行网");document.addTitle("蜗蜗游旅行网电子合同");document.addCreator("蜗蜗游旅行网");document.addHeader("wowoyoo.com", "蜗蜗游");document.addKeywords("蜗蜗游,电子合同 ");document.addSubject("蜗蜗游旅行网电子合同");// 标准化HTML代码org.jsoup.nodes.Document _doc = Jsoup.parse(new File(HTML), "UTF-8");_doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml);String _html = _doc.html();//HTML转PDFXMLWorkerHelper.getInstance().parseXHtml(pdfWriter, document,new ByteArrayInputStream(_html.getBytes()),Charset.forName("UTF-8"), new AsianFontProvider());document.close();}}



    三,中文汉字类,主要是使用了itext-asian包

package com.wowoyoo.helper;import com.itextpdf.text.BaseColor;import com.itextpdf.text.Font;import com.itextpdf.text.pdf.BaseFont;import com.itextpdf.tool.xml.XMLWorkerFontProvider;/** * @author hubs * @version 创建时间:2017年3月21日 下午4:18:49 类说明 */public class AsianFontProvider extends XMLWorkerFontProvider {public Font getFont(final String fontname, final String encoding,final boolean embedded, final float size, final int style,final BaseColor color) {BaseFont bf = null;try {bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);} catch (Exception e) {e.printStackTrace();}Font font = new Font(bf, size, style, color);font.setColor(color);return font;}}


    四,签名类

package com.wowoyoo.helper;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.PrintWriter;import java.security.KeyStore;import java.security.PrivateKey;import java.security.cert.Certificate;import java.security.cert.CertificateFactory;import java.security.cert.X509Certificate;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import com.itextpdf.text.Image;import com.itextpdf.text.PageSize;import com.itextpdf.text.Rectangle;import com.itextpdf.text.pdf.AcroFields;import com.itextpdf.text.pdf.PdfAnnotation;import com.itextpdf.text.pdf.PdfAppearance;import com.itextpdf.text.pdf.PdfReader;import com.itextpdf.text.pdf.PdfSignatureAppearance;import com.itextpdf.text.pdf.PdfStamper;import com.itextpdf.text.pdf.PdfWriter;import com.itextpdf.text.pdf.security.BouncyCastleDigest;import com.itextpdf.text.pdf.security.CertificateInfo;import com.itextpdf.text.pdf.security.CertificateVerification;import com.itextpdf.text.pdf.security.ExternalDigest;import com.itextpdf.text.pdf.security.ExternalSignature;import com.itextpdf.text.pdf.security.MakeSignature;import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;import com.itextpdf.text.pdf.security.PdfPKCS7;import com.itextpdf.text.pdf.security.PrivateKeySignature;import com.itextpdf.text.pdf.security.VerificationException;/** * @author hubs  * @version 创建时间:2017年3月22日 下午3:39:42 * 类说明 */public class Sign {//对PDF进行签名 public static  void signPdf(String src, String dest) throws Exception {KeyStore ks = KeyStore.getInstance("pkcs12", "BC");//证书与证书密码(不要问我是什么意思,我的直接copy网上的....)ks.load(new FileInputStream(Content.PFX_PATH),Content.PFX_PASS.toCharArray());String alias = (String) ks.aliases().nextElement();PrivateKey pk    = (PrivateKey) ks.getKey(alias, Content.PFX_PASS.toCharArray());Certificate[] chain  = ks.getCertificateChain(alias);//读取需要签名的PDF源文件PdfReader reader = new PdfReader(src);//写入目标文件FileOutputStream os  = new FileOutputStream(dest);PdfStamper stamper  = PdfStamper.createSignature(reader, os, '\0');// 加密,只充许打印stamper.setEncryption(Content.OPEN_PASSWORD, null, PdfWriter.ALLOW_PRINTING,PdfWriter.ENCRYPTION_AES_128| PdfWriter.DO_NOT_ENCRYPT_METADATA);int qtyPages = reader.getNumberOfPages();//这个是在每一页的印章(除最后一页)Image _image = Image.getInstance(Content.LOGO_PATH);//这个宽度是图片定位用的float _width = PageSize.A4.getWidth() - _image.getScaledWidth();//设置为A4纸大小Rectangle _rect = PageSize.A4;Rectangle _cell = new Rectangle(_rect);//除了最后一页,其他每页都盖章for (int i = 1; i < qtyPages; i++) {PdfAnnotation stp = PdfAnnotation.createStamp(stamper.getWriter(),_cell, "蜗蜗游旅行网", "wowoyoo.com");// 每一页加标签PdfAppearance tp = PdfAppearance.createAppearance(stamper.getWriter(), _rect.getWidth(), _rect.getHeight());_image.setAbsolutePosition(_width - 50, 50);// X:坐标,Y:右下角坐标tp.addImage(_image, true);stp.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);stamper.addAnnotation(stp, i);}// 最后一个界面加印章Image _last_image = Image.getInstance(Content.STAMP_PATH);PdfAnnotation stp = PdfAnnotation.createStamp(stamper.getWriter(),_cell, "蜗蜗游旅行网", "wowoyoo.com");// 每一页加标签PdfAppearance tp = PdfAppearance.createAppearance(stamper.getWriter(),_rect.getWidth(), _rect.getHeight());_last_image.setAbsolutePosition(_width - 150, 200);// X:坐标,Y:右下角坐标,这里自己调位置tp.addImage(_last_image, true);stp.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);stamper.addAnnotation(stp, qtyPages);PdfSignatureAppearance appearance = stamper.getSignatureAppearance();ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");ExternalDigest digest = new BouncyCastleDigest();MakeSignature.signDetached(appearance, digest, es, chain, null, null,null, 0, CryptoStandard.CMS);}//签证签名(这里暂时只打印出信息,不作判断)/** * 打印结果如下: * Signature name: Signature1 * Signature covers whole document: true *Document revision: 1 of 1 *Subject: {E=[273579540@qq.com], ST=[guanxi], C=[zh], L=[guilin], OU=[wowoyoo], O=[wowoyoo], CN=[wowoyoo]} * Revision modified: false * Certificates verified against the KeyStore * @throws Exception */public static  void verifySignatures() throws Exception {KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());ks.load(null, null);Certificate cert1 = getPublicCertificate();ks.setCertificateEntry("cacert", cert1);PrintWriter out = new PrintWriter(new FileOutputStream(Content.PDF_VERIFICATION));PdfReader reader = new PdfReader(Content.PDF_SIGNED, Content.OPEN_PASSWORD);//这里要加上签名的密码AcroFields af = reader.getAcroFields();ArrayListnames = af.getSignatureNames();for (String name : names) {out.println("Signature name: " + name);out.println("Signature covers whole document: "+ af.signatureCoversWholeDocument(name));out.println("Document revision: " + af.getRevision(name) + " of "+ af.getTotalRevisions());PdfPKCS7 pk = af.verifySignature(name);Calendar cal = pk.getSignDate();Certificate[] pkc = pk.getCertificates();out.println("Subject: "+ CertificateInfo.getSubjectFields(pk.getSigningCertificate()));out.println("Revision modified: " + !pk.verify());Listerrors = CertificateVerification.verifyCertificates(pkc, ks, null, cal);if (errors.size() == 0)out.println("Certificates verified against the KeyStore");elseout.println(errors);}out.flush();out.close();}//公钥证书private static  Certificate getPublicCertificate() throws Exception {FileInputStream is = new FileInputStream(Content.CER_PATH);CertificateFactory cf = CertificateFactory.getInstance("X.509");X509Certificate cert = (X509Certificate) cf.generateCertificate(is);return cert;}}


    五,直接调用

package com.wowoyoo.main;import java.security.Security;import org.bouncycastle.jce.provider.BouncyCastleProvider;import com.wowoyoo.helper.Content;import com.wowoyoo.helper.HtmlToPdf;import com.wowoyoo.helper.Sign;/** * @author hubs * @version 创建时间:2017年3月20日 下午6:03:10 类说明 */public class Main {public static void main(String[] args) throws Exception {Security.addProvider(new BouncyCastleProvider());HtmlToPdf.createPdf(Content.HTML_PATH, Content.PDF_NEW);Sign.signPdf(Content.PDF_NEW, Content.PDF_SIGNED);Sign.verifySignatures();}}


上图:

 

 

依赖类

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>wowoyoo</groupId><artifactId>ConverPdf</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.10</version></dependency><!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian --><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.10.2</version></dependency><!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on --><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.56</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-pdfa</artifactId><version>5.5.10</version></dependency><!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk16 --><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-ext-jdk16</artifactId><version>1.46</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-xtra</artifactId><version>5.5.10</version></dependency><!-- https://mvnrepository.com/artifact/org.bouncycastle/bcmail-jdk16 --><dependency><groupId>org.bouncycastle</groupId><artifactId>bcmail-jdk16</artifactId><version>1.46</version></dependency><!-- https://mvnrepository.com/artifact/org.bouncycastle/bctsp-jdk16 --><dependency><groupId>org.bouncycastle</groupId><artifactId>bctsp-jdk16</artifactId><version>1.46</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.16-beta2</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.7-beta3</version></dependency><dependency><groupId>com.itextpdf.tool</groupId><artifactId>xmlworker</artifactId><version>5.5.10</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.18</version></dependency></dependencies></project>


 最后感谢网上提供的资源,由于找资源时太乱太杂了,没能记下资源原地址,在此表示感谢。

from : http://hihubs.com/article/274

0 0
原创粉丝点击