ORACLE通过utl_http传送加密数据实现第三方接口
@ORACLE通過utl_http傳送加密數據實現第三方接口
ORACLE通過utl_http傳送加密數據實現第三方接口
最近這個項目已經到了收尾階段,再不總結就要忘記。抓緊時間出成品:
項目是一個三方接口,說到接口就離不開數據的收集、數據傳送兩個方面。
數據收集,有關客戶機密這個先放一邊暫且不討論。
數據傳送方面涉及兩個方面,也是今天總結中的主體-HTTP請求、數據加密
這次的項目是把加密的各種數據轉換函數溜了一遍,在各平臺尋找資料時也碰到一些奇怪的現象:
公開代碼沒有交待測試環境–》這就導致有讀者看到代碼后無法實現代碼的重寫。
有些公開代碼還算完整,有些就只是一些只言片語,看了真是一頭霧水。
這就要各位讀者朋友養成一雙火眼金睛,能分辨出那些是可利用的,那些是不可利用的。
其中,也把自己踩過的坑記錄下來,避免下次再踩進去。
另一個就是HTTP請求,它的整個流程如下:
1.建立連接:向服務器發送請求之前需要建立連接,通過DNS服務器創建套接字、建立連接、收發數據等操作查詢ip地址,再建立socket連接。
2.發送請求:連接成功后,向Web服務器發送http消息格式的請求,包括get、post等命令。
3.響應、應答:web服務器收到請求后,從它的文檔空間中搜索子目錄index的文件index.html,并把其傳送給web服務器,再將具體信息傳遞回瀏覽器。—第三方接收,響應并回復的一個過程。
4.關閉連接:Web瀏覽器與Web服務器斷開,以保證其他Web瀏覽器能與Web服務器建立連接。
PROCEDURE RECEIVE_HTTP(p_addr_type in varchar2,p_json in varchar2, p_org_no in number, p_so_pos_no in varchar2, p_so_no in varchar2, p_job_start_pk_no in number, p_serial_no in number)
IS
PRAGMA autonomous_transaction;
REQ UTL_HTTP.REQ;
RESP UTL_HTTP.RESP;
VALUE VARCHAR2(32000);
v_url varchar2(2014);
v_tokens varchar2(256);
v_msg varchar2(3000) := null;
v_job_step_pk_no number := null;
v_job_end_pk_no number := null;
v_serial_no number;
send_failed_exception exception;
v_step number;
v_status_flg VARCHAR2(32);
BEGIN
v_url := get_webaddress(v_tokens,p_addr_type, p_json); --獲得URL地址
utl_http.set_body_charset(‘UTF-8’);–解決接收返回值及信息亂碼問題。
req := UTL_HTTP.BEGIN_REQUEST (url=> v_url,method => ‘POST’); --該參數代表請求包含POST數據
utl_http.set_header(req, ‘Keep-Alive’, ’ timeout=1’);–該參數代表超時,這里我并沒用,主要是JOB間隔太近,沒必要。
UTL_HTTP.SET_HEADER (r => req,name => ‘Content-Type’,VALUE => ‘application/json;charset=UTF-8’);
UTL_HTTP.SET_HEADER (r => req,name => ‘Content-Length’,VALUE => LENGTHB(p_json));
----該參數代表我發送的POST報文多長,不可少 。這里之所以使用LENGTHB而未使用LENGTH,是因為發現如果發送內容中有中文LENGTHB獲得值才是正確的長度。
UTL_HTTP.WRITE_TEXT (r => req,data => p_json);
resp := UTL_HTTP.GET_RESPONSE(req);
UTL_HTTP.READ_text(resp,value );
–UTL_HTTP.READ_line(resp,value ,true); 這里之前使用read_line,出現ORA-29273: HTTP request failed ORA-06512: at “SYS.UTL_HTTP”, line 1355 ORA-06502: PL/SQL: numeric or value error等問題。
–后來查詢發現read_line多與LOOP合用。多如下使用:
/LOOP
UTL_HTTP.READ_LINE ( resp, v_line, TRUE );
END LOOP;/
IF INSTR(VALUE,‘“code”:“0”’)> 0 THEN
–pass
–add log
v_status_flg :=‘Y’;
ELSE
–error
–add log
–這里想使用一個異常,一直沒找到適合的ORACLE內置的索性改個方法顯示目的。
v_status_flg :=‘F’;
END IF;
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
when others then
–add log
rollback;
END RECEIVE_HTTP;
加密算法
接一下就是加密,何為加密?換個說法就是轉碼就像數字的表示方法有十進制、二進制一樣,一個數字可用不同方法表示,只要解讀者知道怎么解讀就能準確的拿到相要的東西。
之前只使用過MD5,第三方加密方法和邏輯特別繁瑣,這也使我接觸多種加密算法。
Base64
實質是一種編碼格式,如同UTF-8
是一種用64個字符來表示任意二進制數據的方法
可逆性
可以將圖片等二進制文件轉換為文本文件
可以把非ASCII字符的數據轉換成ASCII字符,避免不可見字符
MD5
實質是一種散列表的計算方式
不可逆性。
任意長度的明文字符串,加密后得到的密文字符串是長度固定的。
SHA1
Sha1是一種密碼散列函數,是一個用來進行數字簽名的算法。這種算法通俗來說,就是接收一段明文,并以不可逆的方式轉換成一段密文,通過密文無法知道原文是什么。
SHA1先對任意長度的明文進行分組,每一組的長度為512位,然后對這些明文分組反復重復處理。
AES
數據庫中的數據如果是包含有敏感信息,或者需要對一些數據進行加密,為了方便數據庫處理或者對數據表中已存在的原有的數據進行加密,則可以使用Oralce中的AES加密函數來進行數據的加密.
需要注意的是:無論是AES128與AES192都需要密鑰。
如:AES128加密密鑰key是16位,AES192加密密鑰key是24位。
加密方式:
密鑰位數:AES128 DBMS_CRYPTO.ENCRYPT_AES128
連接方式:CBC/ECB DBMS_CRYPTO.CHAIN_CBC/CHAIN_ECB
填充方式:PKCS5 DBMS_CRYPTO.PAD_PKCS5
function get_token( p_values in varchar2 , p_type in varchar2)
return varchar2
is
v_tokens varchar2(128);
----QR—
vs_key varchar2(128) :=‘A5d9X27ad047XXXXXfaa00cXX23’;
vs_data varchar2(20000);
vr_sha1_key1 raw(256); –
vr_sha1_key2 raw(256);
vs_aes_key varchar2(2000);
vr_aes_data raw(32000);
vr_base64_data raw(32000);
vs_target_data varchar2(32000);
vs_temp varchar2(30000);
begin
if p_type = ‘PRE’ then
select replace(replace(utl_raw.cast_to_varchar2(utl_encode.BASE64_ENCODE(utl_raw.cast_to_raw(p_values))), chr(13)),chr(10))
–BASE64,這里使用轉換函數BASE64_ENCODE的函數的需要ROW類型,所以先轉成ROW型,加密后再轉為VARCHAR2型。replace的使用是為了截取掉換行和回車,chr(10) 換行 chr(13) 回車。
into v_tokens
from dual;
select lower(dbms_crypto.hash(utl_raw.cast_to_raw(v_tokens), dbms_crypto.HASH_SH1 )) --SHA1,lower的原因是由dbms_crypto.hash得到的值為大寫,需要轉換成小寫。
into v_tokens
from dual;
return v_tokens;
elsif p_type = ‘QR’ then
–sha1 once for key
select dbms_crypto.hash(utl_raw.cast_to_raw(vs_key), dbms_crypto.HASH_SH1) into vr_sha1_key1 from dual;
vs_temp := replace(replace(utl_raw.cast_to_varchar2(vr_sha1_key1),chr(10)),chr(13));
–sha1 twice for key
select dbms_crypto.hash(utl_raw.cast_to_raw(vs_temp), dbms_crypto.HASH_SH1) into vr_sha1_key2 from dual;
vs_temp := replace(replace(utl_raw.cast_to_varchar2(vr_sha1_key2),chr(10)),chr(13));-- 經過兩次加密獲得KEY串
–get 1-16 chars as aes_key
select substrb(utl_raw.cast_to_varchar2(vr_sha1_key2),1,16) into vs_aes_key from dual; --通過截取之前的KEY串,獲得16位KEY
–get aes_text
vr_aes_data := dbms_crypto.encrypt(utl_raw.cast_to_raw(p_values),dbms_crypto.encrypt_aes128+dbms_crypto.chain_ecb+dbms_crypto.pad_pkcs5,utl_raw.cast_to_raw(vs_aes_key)); --AES128
–get base64_encoded data
vr_base64_data := utl_encode.base64_encode(vr_aes_data);
–get urlencode data
vs_target_data := utl_url.escape(replace(replace(utl_raw.cast_to_varchar2(vr_base64_data),chr(10)),chr(13)),TRUE,‘UTF8’);
return vs_target_data;
end if;
end;
附:
加密方式選擇:
Oracle官方給出的選擇有:
總結
以上是生活随笔為你收集整理的ORACLE通过utl_http传送加密数据实现第三方接口的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【WordPress】添加备案信息
- 下一篇: Java API 1.8 中文版 免费下