讓Content-Disposition解決非英文檔案,下載亂碼問題

這是老問題了,很多老外都忽略這個,我在協助teedy翻譯時,發現下載中文檔案中文會出現空白,看一下程式原來是忘了進行編碼導致,就順手提交一下解法。

#以下為java虛擬碼
CONTENT_DISPOSITION, "inline; filename*=utf-8''" + filenameEncode( "檔名" )

private String filenameEncode(String name) {
try {
return java.net.URLEncoder.encode(name, "UTF-8").replace("+", "%20");
} catch (java.io.UnsupportedEncodingException e) {
e.printStackTrace();
return name;
}
}

參考 :

好用的文管系統 Teedy

Teedy這是一款很棒的軟體,以文件為本,文件具有唯一性,但又能同時出現在不同目錄結構(使用Tag)

此舉可避免一般傳統檔案總管,相同文件需要在不同目錄出現而複製多份;若遇到文件因設計變更而改版,會造成文員文件版本維護困難。

Teedy 系統能綁定網域主控(Ldap)、有權限設定、全文檢索,也有文件提交送審功能,功能全面。

更難得的是,除了上述功能,該系統具備審計軌跡Audit Log,能符合ISO文管系統的基本要求,能讓稽核員認同的一個系統,要過ISO13485、ISO62304沒難度。

Teedy系統採用微軟GitHub管轄下的開源軟體,不用錢;軟體確效會很簡單(只需做3Q),風險超低,因其開源特性,全世界的工程師都可檢驗。

此開源系統比套裝軟體風險更低,建議服用。但缺點是翻譯超爛,我花了很多時間協助翻譯。有興趣安裝的請參考這裡

我認為OpenProject可用來規劃、追蹤進度,產生的文件可以提交到Teedy進行管控,補足OpenProject文件管理的不足.

又是windows 11,停用TLS 1.0、TLS 1.1,只支援1.2

windows 11 從2024年開始,預設就停用TLS 1.0、TLS 1.1了。

表姊公司dovecot 內送郵件伺服器沒有支援TLS 1.2,解法就兩種

  1. 啟用windows 11 TLS 1.0、TLS 1.1
    https://learn.microsoft.com/en-us/windows/win32/secauthn/tls-10-11-deprecation-in-windows
  2. 讓dovecot相容TLS 1.2
    重點在Linux Server上的openssl 版本必須1.0.1或以上
    dovecot啟用TLS 1.2 做法如下:
    https://serverfault.com/questions/959186/error-performing-tls-handshake-with-dovecot-2-3-upgrade

我自己修改dovecot啟用TLS 1.2 做法如下:

  1. 產生dh.pem
    openssl dhparam 4096 > /etc/dovecot/dh.pem
  2. 修改 /etc/dovecot/conf.d/10-ssl.conf

ssl_dh =</etc/dovecot/dh.pem
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL
ssl_prefer_server_ciphers = yes

最後再更新我自己整合的郵件伺服器(綁定本地端微軟網域伺服器)
https://github.com/WilliamFromTW/docker-Postfix-AD


2024/01/10 (冏只隔一天又出現其他問題)

上次問題解決之後(windows 11其實有更新到24h2),後續又發現其他台windows 11未更新24h2,收發信還是有問題,但問題不太一樣

Jan 10 09:49:02 docker dovecot: pop3-login: Disconnected: Connection closed: SSL_accept() failed: error:1417A0C1:SSL routines:tls_post_process_client_hello:no shared cipher 

我除了更新mail server的postfix 、dovecot、openssl (RockyLinux 8.8) 外,變更dovecot一些設定,就解決問題了。

  1. 啟用windows 11 的TLS 1.0 、TLS 1.1
    依照微軟建議,我做成reg檔案,請按此下載匯入到windows啟用
  2. 更改dovecot設定,改成最小可支援 TLS 1.1 ,ssl_cipher_lis也修改(出處請參照這裡)
ssl_min_protocol = TLSv1.1
#ssl_cipher_list = ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW:!DH@STRENGTH
ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL

win11 22h2帶來的影響,無法連線MSSQL 2005

我表姊公司在1999年就開始使用高格EPR系統,這個系統使用當時開發windows程式的顯學 Borland 軟體架構(2-tier、3-tier),資料庫使用interbase 。

高格一路上升級,資料庫改成BDE+mssql 2005混合體,連線方式從netbeui改tcpip,用戶端作業系統從windown 98到windows 10也能使用。

我認為高格是一款很棒的軟體,不比我二姊公司現在還在使用生產力中心開發的老古董”excel 97 進銷存系統”差。

直到最近,表姊公司換新的筆電,原本依照步驟,將windows啟用.net framework 3.5、smb 1.0 ,安裝interbase、mssql 2005 client 就可以連到 mssql 2005 server,實際上安裝後,卻無法正常連線到資料庫;我找了很久找不出原因,只好google一下”win11 mssql 2005″,居然在ITHOME找到解法 https://ithelp.ithome.com.tw/questions/10212352(感謝 aaron3399mihihi) ,只要利用 IISCrypto 這個軟體(備用下載),將win11被移除的加密方式加回來,就可以連上mssql 2005 server了,也讓高格能繼續生存下去。

加回來的加密協定:

TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_3DES_EDE_CBC_SHA

國外參考

老派java+eclipse+sprint boot遇到3DES加密問題

API,傳資料只用簡單的3DES加解密,但是java 預設只有3DES的PKCS5Padding,要達到PKCS7Padding(windows c# 只支援PKCS7Padding),就只能請Bouncy Castle幫忙,我使用bcprov-jdk15to18-1.78.1.jar、jdk17。

程式改寫大概如下:

// java 只有padding5,用bouncycastle,改寫成可使用padding7
static {
if(Security.getProvider("BC")!=null) Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
}


// 使用CBC、PKCS7Padding
原本寫法
Cipher decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
改成
Cipher decryptCipher = Cipher.getInstance("DESede/CBC/PKCS7Padding","BC");

在Eclipse開發時很正常,正式執行時,出現以下錯誤:

jce cannot authenticate the provider bc

我查了一下原來jdk 17是17.0.9版,這問題於jdk 17.0.10(2024年1月)解決,就這麼剛好只差一版;最後,我升級至目前最新 jdk17.0.12版就解決了。參考來源


另外 windows uwp c#寫法也幾乎一至,因java是API,windows app為client,所以也就順手了解一下

public static String Encrypt3DesCbcPKCS7Padding(String sIV,String sSecretKey, String sData)
{
TripleDES tdes = TripleDES.Create();
IvParameterSpec ivSpec = new IvParameterSpec(System.Text.Encoding.UTF8.GetBytes(sIV));
SecretKeySpec secretKeySpec = new SecretKeySpec(System.Text.Encoding.UTF8.GetBytes(sSecretKey), "DESede");
Cipher encryptCipher = Cipher.GetInstance("DESede/CBC/PKCS7Padding", "BC");
encryptCipher.Init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
return Base64.ToBase64String(encryptCipher.DoFinal(System.Text.Encoding.UTF8.GetBytes(sData)));

}
1 2 3 ... 76