1. 程式人生 > >新手如何使用itext7生成pdf蓋章

新手如何使用itext7生成pdf蓋章

array reason style throw wid vid 摘要 都是 中文

  一開始,我使用的是itext2.1.7,但是會出現中文不能顯示問題,解決方案:下載另一個包extrajars-2.3.zip,此包中的itext-asian.jar可以幫助解決中文亂碼問題,若再遇到STSong-Light‘ with ‘UniGB-UCS2-H‘ is not recognized問題,可以點擊鏈接進行解決。如若再無解決,請放棄itext2.1.7直接用itext7吧,itext7中自帶解決中文顯示問題。具體如下:

一、使用的工具

  1.編譯環境:eclipse mars2

   2.運行環境:jdk1.7

   3.itext包 :itext7.0.2

   3.相關jar包:bcprov-jdk15on-157.jar,bcpkix-jdk15on-157.jar (這兩個一定要有,不然會報錯,其他包看情況而定,參考鏈接裏面JDK 1.5 - JDK 1.8)

二、生成test.keystore文件

  生成方法請參考博客《使用Keytool工具生成證書Keystore和證書簽名請求文件》

     如下圖(名字可以隨便取):

技術分享

三、代碼前準備

   1.先把生成好的 test.keystore文件放入 jdk1.7\bin目錄下

   2.把 bcprov-jdk15on-157.jar放入 jdk1.7\jre\lib\ext目錄下

   3.配置安全屬性文件:在 jdk1.7\jre\lib\security目錄下有個java.security文件,用它定義了當前可以使用的加密提供者。如看到下面的語句:

     security.provider.1=sun.security.provider.Sun

     security.provider.2=sun.security.rsa.SunRsaSign

   它表明本虛擬機有兩個加密提供者以及他們的優先級和訪問時使用的名稱。當需要用到一個加密算法時,虛擬機會依次訪問這裏列出的提供者,尋找想要的算法,

   並按這裏的優先級順序使用第一個找到的算法。我們應該在文件中插入新的提供者例如:

    security.provider.3=org.bouncycastle.jce.provider.BouncyCastleProvider

   例如下圖:

技術分享

   4.先創建一個java工程,導入jar包,如下圖(紅色框內為後面運行時報出異常後添加的包)

技術分享

四、代碼編寫

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;

import javax.swing.JOptionPane;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.io.image.ImageData; import com.itextpdf.io.image.ImageDataFactory; import com.itextpdf.kernel.geom.PageSize; import com.itextpdf.kernel.geom.Rectangle; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.layout.element.Image; import com.itextpdf.signatures.BouncyCastleDigest; import com.itextpdf.signatures.DigestAlgorithms; import com.itextpdf.signatures.IExternalDigest; import com.itextpdf.signatures.IExternalSignature; import com.itextpdf.signatures.PdfSignatureAppearance; import com.itextpdf.signatures.PdfSignatureAppearance.RenderingMode; import com.itextpdf.signatures.PdfSigner; import com.itextpdf.signatures.PdfSigner.CryptoStandard; import com.itextpdf.signatures.PrivateKeySignature; public class SignPDF { public static final String KEYSTORE = "E:\\Program Files\\jdk1.7\\bin\\test.keystore";//keystore文件路徑 public static final char[] PASSWORD = "123456".toCharArray(); // keystore密碼 public static final String SRC = "C:\\Users\\xxx\\Desktop\\歡迎信.pdf";//需要蓋章的pdf文件路徑 public static final String DEST = "C:\\Users\\xxx\\Desktop\\歡迎信2.pdf";//蓋章後生產的pdf文件路徑 public static final String stamperSrc = "C:\\Users\\xxx\\Desktop\\self_study\\stamper\\stamper7.png";//印章路徑 public void sign(String src //需要簽章的pdf文件路徑 , String dest // 簽完章的pdf文件路徑 , Certificate[] chain //證書鏈 , PrivateKey pk //簽名私鑰 , String digestAlgorithm //摘要算法名稱,例如SHA-1 , String provider // 密鑰算法提供者,可以為null , CryptoStandard subfilter //數字簽名格式,itext有2種 , String reason //簽名的原因,顯示在pdf簽名屬性中,隨便填 , String location) //簽名的地點,顯示在pdf簽名屬性中,隨便填 throws GeneralSecurityException, IOException { //下邊的步驟都是固定的,照著寫就行了,沒啥要解釋的 PdfReader reader = new PdfReader(src); PdfDocument document = new PdfDocument(reader); document.setDefaultPageSize(PageSize.TABLOID); //目標文件輸出流 FileOutputStream os = new FileOutputStream(dest); //創建簽章工具PdfSigner ,最後一個boolean參數 //false的話,pdf文件只允許被簽名一次,多次簽名,最後一次有效 //true的話,pdf可以被追加簽名,驗簽工具可以識別出每次簽名之後文檔是否被修改 PdfSigner stamper = new PdfSigner(reader, os, true); // 獲取數字簽章屬性對象,設定數字簽章的屬性 PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); appearance.setReason(reason); appearance.setLocation(location); ImageData img = ImageDataFactory.create(stamperSrc); //讀取圖章圖片,這個image是itext包的image Image image = new Image(img); float height = image.getImageHeight(); float width = image.getImageWidth(); //設置簽名的位置,頁碼,簽名域名稱,多次追加簽名的時候,簽名與名稱不能一樣 //簽名的位置,是圖章相對於pdf頁面的位置坐標,原點為pdf頁面左下角 //四個參數的分別是,圖章左下角x,圖章左下角y,圖章寬度,圖章高度 appearance.setPageNumber(1); appearance.setPageRect(new Rectangle(350, 100, width, height)); //插入蓋章圖片 appearance.setSignatureGraphic(img); //設置圖章的顯示方式,如下選擇的是只顯示圖章(還有其他的模式,可以圖章和簽名描述一同顯示) appearance.setRenderingMode(RenderingMode.GRAPHIC); // 這裏的itext提供了2個用於簽名的接口,可以自己實現,後邊著重說這個實現 // 摘要算法 IExternalDigest digest = new BouncyCastleDigest(); // 簽名算法 IExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, BouncyCastleProvider.PROVIDER_NAME); // 調用itext簽名方法完成pdf簽章 stamper.setCertificationLevel(1); stamper.signDetached(digest,signature, chain, null, null, null, 0, PdfSigner.CryptoStandard.CADES); } public static void main(String[] args) { try { // 讀取keystore ,獲得私鑰和證書鏈 jks KeyStore ks = KeyStore.getInstance("jks"); ks.load(new FileInputStream(KEYSTORE), PASSWORD); String alias = (String) ks.aliases().nextElement(); PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD); Certificate[] chain = ks.getCertificateChain(alias); // new一個上邊自定義的方法對象,調用簽名方法 SignPDF app = new SignPDF(); app.sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, null, CryptoStandard.CADES, "Test 1", "Ghent"); } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage()); e.printStackTrace(); } } }

五,生成後的結果如下圖所示

技術分享

  技術分享

要蓋章的文檔必須是通過itext已經生成完後的文檔,或者蓋章的同時生成文檔,不然章蓋不上去!!

  如下圖:

  技術分享

技術分享

  

技術分享

新手如何使用itext7生成pdf蓋章