眾所周知,在web應用的api中,總是會出現資料庫item的id。比如get /posts/1
表示獲取id為1的文章內容。這樣做十分簡潔,但存在被人爬資料的風險。比如我可以大致猜測或者試一下id的範圍,1,2,3...10000這樣迭代地爬資料。如果伺服器不做訪問限制,很輕易就能把所有資料就能爬下來。而且,這樣的數字id也會暴露一些資訊,比如id小的一般是更早建立的。
所以要對id進行混淆,混淆有這麼幾個特點:
它是乙個無符號整數到字串的一一對應的函式
雙向的,混淆之後可以恢復,所以不能用hash
不表現出遞增的特徵
不用像加密那樣強,也不用有金鑰
沒有整數範圍的限制。這一條是我加的,google能搜到很多id混淆的方法但它們可能要求id在2^32-1之內,比如對2^32求乙個multiplicative inverse,這是乙個不錯的方法但因為這個限制我沒有採用它。
最簡單的乙個方法是找乙個比較大的數字進行異或,比如1-10跟1093420374進行異或的結果是這樣的:
1 : 1093420375
2 : 1093420372
3 : 1093420373
4 : 1093420370
5 : 1093420371
6 : 1093420368
7 : 1093420369
8 : 1093420382
9 : 1093420383
10: 1093420380
但這比較容易被人猜出是異或,需要再加上別的操作
我看到的乙個比較好的方法也是我目前在用的是:
對id求個hash,取前16位元組,作為segment1
對segment1求hash,取前8位元組,作為segment2
將segment2轉換為整數,加上id,再變回byte array
將segment1和segment2連線起來再求個hash,取前8位元組,作為segment3(用於恢復時的驗證)
連線segment1、2、3,做base64,得到混淆後的id
恢復的時候只用
base64解碼
取前16位元組得到segment1,後8位元組得到segment3,剩餘位元組是segment2
驗證hash(segmemt1+segment2)是否等於segment3
int(segment2)-int(hash(segment1))得到id
這用python實現比較方便,因為python的整數可以無限大,**是這樣的
class
obfuscator:
_head_bytes = 16
_mid_bytes = 8
_tail_bytes = 8
@staticmethod
defbytearray_to_int
(byte_arr):
return int.from_bytes(byte_arr, byteorder='big')
@staticmethod
defint_to_bytearray
(num):
assert isinstance(num, int) and num >= 0
if num == 0:
return
b'0'
result =
while num > 0:
d, m = divmod(num, 256)
num = d
return bytes(result[::-1])
@classmethod
defobfuscate
(cls, uid):
ifnot uid:
return
'' uid_bytes = cls.int_to_bytearray(uid)
seg1 = hashlib.sha1(uid_bytes).digest()[:cls._head_bytes]
seg2 = hashlib.sha1(seg1).digest()[:cls._mid_bytes]
seg2 = cls.int_to_bytearray(uid + cls.bytearray_to_int(seg2))
seg3 = hashlib.sha1(seg1 + seg2).digest()[:cls._tail_bytes]
return base64.urlsafe_b64encode(seg1 + seg2 + seg3).decode()
@classmethod
defrestore
(cls, obscure_str):
ifnot obscure_str:
return -1
seg_bytes = base64.urlsafe_b64decode(obscure_str)
seg1 = seg_bytes[:cls._head_bytes]
seg2 = seg_bytes[cls._head_bytes:-cls._tail_bytes]
seg3 = seg_bytes[-cls._tail_bytes:]
if hashlib.sha1(seg1 + seg2).digest()[:cls._tail_bytes] != seg3:
return -1
seg1 = hashlib.sha1(seg1).digest()[:cls._mid_bytes]
return cls.bytearray_to_int(seg2) - cls.bytearray_to_int(seg1)
反射的另外一種方法
t instance default t type type typeof t system.reflection.constructorinfo constructorinfoarray type.getconstructors system.reflection.bindingflags.ins...
模糊查詢和一種方法
通過這種方法來模糊查詢,可以自定義匹配hql語句 public listsearchuser user user,pageinfo pageinfo else catch exception e 設定query值 private void setvalue query q,user user if ...
解決 side by side 問題的一種方法
vs7.0開始引入了manifest的機制,程式必須經過部署才能執行。release版本的程式可以通過安裝vc 的redistributable包完成部署。debug版本的程式微軟沒有提供對應的redistributable包。如果在沒有安裝vs的機器上執行就會遇到side by side錯誤。對此...