1. 程式人生 > 其它 >電子公文系統

電子公文系統

個人貢獻值

本人對於此專案的貢獻是檔案傳輸和使用者口令的保護,及負責整個系統密碼安全

實踐過程

首先建立資料庫連線使用者名稱密碼

進入mysql本地

建立自己使用者名稱(20201325xjr)

為“20201325xjr”授全部許可權

檢視資料庫使用者是否新增成功

我們發現已經建立成功啦!

修改idea專案通過20201325xjr連線資料庫

就成功啦!!!

專案中資訊保護方法

此電子公文系統採用的是呼叫openssl演算法庫中的指令對資料進行加解密。首先我們來看一下專案crypto層的openssl類

crypto.Openssl

該專案的檔案傳輸使用SM4對稱加密,金鑰分配通過使用rand生成16位元組的隨機數,使用者密碼使用SM3演算法計算摘要值。部分程式碼如下:

SM3

public static String SM3(String data) throws IOException {
			List<String> commandArr = new ArrayList<>();
			commandArr.add("/bin/sh");
			commandArr.add("-c");
			String cmd = "echo "+data+" | openssl sm3";
			commandArr.add(cmd);
			String result = RunCmd.run(commandArr.toArray(new String[commandArr.size()]));
			return result.substring(9);			
		}

SM4

public static void SM4encrypt(String filePath,String key) throws IOException {
			String cmd = "openssl sm4 -in " + filePath + " -out " + filePath + ".en -K " + key + " -iv " + key;
			RunCmd.run(cmd);
		}
		public static void SM4decrypt(String filePath,String key) throws IOException {
			String cmd = "openssl sm4 -d -in " + filePath + ".en -out " + filePath + " -K " + key + " -iv " + key;
			RunCmd.run(cmd);
		}

rand16

public static String rand16() throws IOException {
			//生成16位元組的隨機數
			String cmd = "openssl rand -hex 16";
			String result = RunCmd.run(cmd);
			return result;
		}

由程式碼我們可以看出使用的是openssl命令列指令對資料進行加密解密。通過建立cmd變數儲存待加密的檔案路徑和金鑰,然後傳入RunCmd類中的run方法進行執行。

dao.UserDao

我們通過看專案dao層的程式碼來看使用者的口令保護程式

註冊使用者

可以看到使用者在頁面進行互動後傳入的密碼要先通過Openssl中的SM3方法之後再被放入sql字串中進行insert。

然後通過PreparedStatement類的setString方法進行傳入引數,其中每個使用者自己的對稱金鑰通過Openssl中的rand16方法進行生成

引數值與資料庫對應關係如下:

使用者登入

可以看到使用者在登入的時候會首先通過select語句進行尋找使用者名稱,找到使用者名稱之後通過使用者名稱尋找其id、name、password、level,隨後通過if判斷密碼摘要值來決定使用者身份。

上傳公文controller.UploadServlet

我們在controller層的UploadServlet類中新增加密傳輸程式碼

加密核心程式碼

            //使用使用者的對稱金鑰對檔案加密
            Openssl.SM4encrypt(path+filePath, u.getEncrykey());
            //刪除明文
            Openssl.deletePlain(path+filePath);

上傳公文 UploadServlet(xjr發給tsx)

定義儲存路徑

path為伺服器儲存的公文地址

獲取上傳檔名

  • 首先通過req.getPart方法獲取檔案存入part物件中

Part part = req.getPart("file");

  • 隨後定義disposition變數獲取檔案的路徑及名字

String disposition = part.getHeader("Content-Disposition");

  • 使用substring方法獲取路徑中最後的那個檔名,如:*.txt

String realFileName = disposition.substring(disposition.lastIndexOf("=\"") + 2, disposition.length()-1);

  • 隨後使用InputStream類定義一個物件is並用getInputStream方法獲取part中檔案的資料流

InputStream is = part.getInputStream();

  • 動態獲取伺服器路徑

此處使用了UUID.randomUUID().toString方法。

String filePath = String.format("/%s/%s", UUID.randomUUID().toString(), realFileName);

我們嘗試用System.out.println輸出filePath看看如下:

此處我上傳了一個1.txt,前面路徑是伺服器當前的路徑

  • 獲取檔案

使用Path類定義一個file變數,並使用get方法獲取檔案

Path file = Paths.get(path, filePath);

  • 輸出檔案流

使用FileOutputStream類建立物件fos進行輸出檔案流

FileOutputStream fos = new FileOutputStream(file.toFile());
byte[] bty = new byte[1024];
            int length =0;
            while((length=is.read(bty))!=-1){
                fos.write(bty,0,length);
            }
  • 檔案加密

此處使用了Openssl.SM4encrypt方法對檔案進行加密,注意:此處加密檔案路徑為path+filePath,即/home/xjr/桌面/Project2/file/伺服器動態路徑/filename

Openssl.SM4encrypt(path+filePath, u.getEncrykey());

對照剛剛的System.out.println輸出的filePath結果我們看看是否生成對應檔案目錄

可以發現已經成功!

下載公文controller.DownServlet

解密核心程式碼

Openssl.SM4decrypt(path,key);

下載公文過程

  • 獲取客戶端需要下載的檔名

此處建立了一個file字串存取資料庫動態地址+檔名

String file = request.getParameter("file");

我們可以使用System.out.println(file);對其驗證:

  • 獲取檔案絕對地址

定義一個path字串,儲存專案路徑+伺服器動態路徑+檔名

String path = UploadServlet.path+"/"+file; //預設認為檔案在當前專案的根目錄

  • 獲取傳送者資訊

定義字串sender儲存傳送者名字,並使用documentService類中的findDocumentByPath和getSendUser方法進行查詢傳送者名字。

String sender = documentService.findDocumentByPath(file).getSendUser();

  • 獲取解密金鑰

由於使用的是SM4演算法,此演算法為一個對稱密碼演算法,故需要將獲取傳送方的金鑰。

這裡使用了userService類中的getEncrykey方法;

key = userService.findUserByName(sender).getEncrykey();

這裡我們用xjr使用者給tsx使用者傳送公文,隨後tsx下載公文為例,用System.out.println(key);檢視key值

  • 解密

此處使用了Openssl.SM4decrypt方法進行解密

Openssl.SM4decrypt(path,key);

將目標檔案解密後得到: