1. 程式人生 > 其它 >網站安全防範 關於觀看了一個小網站被打的視訊感想

網站安全防範 關於觀看了一個小網站被打的視訊感想

1、什麼是介面冪等性

介面冪等性就是使用者對於同一操作發起的一次請求或者多次請求的結果是一致的,不會因為多次點選而產生了副作用;比如說支付場景,使用者購買了商品支付扣款成功,但是返回結果的時候網路異常,此時錢已經扣了,使用者再次點選按鈕,此時會進行第二次扣款,返回結果成功,使用者查詢餘額返發現多扣錢了,流水記錄也變成了兩條...,這就沒有保證介面的冪等性


2、什麼情況下需要冪等

使用者多次點選按鈕使用者頁面回退再次提交微服務互相呼叫,由於網路問題,導致請求失敗。feign 觸發重試機制


3、冪等性舉例

以 SQL 為例,有些操作是天然冪等的。 SELECT * FROM table WHER id=?,無論執行多少次都不會改變狀態,是天然的冪等。

UPDATE tab1 SET col1=1 WHERE col2=2,無論執行成功多少次狀態都是一致的,也是冪等操作。

delete from user where userid=1,多次操作,結果一樣,具備冪等性

insert into user(userid,name) values(1,'a') 如 userid 為唯一主鍵,即重複操作上面的業務,只會插入一條使用者資料,具備冪等性


UPDATE tab1 SET col1=col1+1 WHERE col2=2,每次執行的結果都會發生變化,不是冪等的。

insert into user(userid,name) values(1,'a') 如 userid 不是主鍵,可以重複,那上面業務多次操作,資料都會新增多條,不具備冪等性


4、冪等解決方案

1)token機制

①、服務端提供了傳送 token 的介面。我們在分析業務的時候,哪些業務是存在冪等問題的,就必須在執行業務前,先去獲取 token,伺服器會把 token 儲存到 redis 中。

②、然後呼叫業務介面請求時,把 token 攜帶過去,一般放在請求頭部。

③、伺服器判斷 token 是否存在 redis 中,存在表示第一次請求,然後刪除 token,繼續執行業務。

④、如果判斷 token 不存在 redis 中,就表示是重複操作,直接返回重複標記給 client,這樣就保證了業務程式碼,不被重複執行


這種方式存在的危險性

【注意】

保證:從redis取值,比較,刪除redis的key是一個原子操作

if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end



2)各種鎖機制

①、資料庫悲觀鎖 select * from xxxx where id = 1 for update; 悲觀鎖使用時一般伴隨事務一起使用,資料鎖定時間可能會很長,需要根據實際情況選用。另外要注意的是,id 欄位一定是主鍵或者唯一索引,不然可能造成鎖表的結果,處理起來會非常麻煩。


②、資料庫樂觀鎖這種方法適合在更新的場景中, update t_goods set count = count -1 , version = version + 1 where good_id=2 and version = 1 根據 version 版本,也就是在操作庫存前先獲取當前商品的 version 版本號,然後操作的時候帶上此 version 號。我們梳理下,我們第一次操作庫存時,得到 version 為 1,呼叫庫存服務 version 變成了 2;但返回給訂單服務出現了問題,訂單服務又一次發起呼叫庫存服務,當訂單服務傳如的 version 還是 1,再執行上面的 sql 語句時,就不會執行;因為 version 已經變為 2 了,where 條件就不成立。這樣就保證了不管呼叫幾次,只會真正的處理一次。樂觀鎖主要使用於處理讀多寫少的問題


③、業務層分散式鎖如果多個機器可能在同一時間同時處理相同的資料,比如多臺機器定時任務都拿到了相同資料處理,我們就可以加分散式鎖,鎖定此資料,處理完成後釋放鎖。獲取到鎖的必須先判斷這個資料是否被處理過


3)各種唯一約束

①、資料庫唯一約束插入資料,應該按照唯一索引進行插入,比如訂單號,相同的訂單就不可能有兩條記錄插入。我們在資料庫層面防止重複。這個機制是利用了資料庫的主鍵唯一約束的特性,解決了在 insert 場景時冪等問題。但主鍵的要求不是自增的主鍵,這樣就需要業務生成全域性唯一的主鍵。如果是分庫分表場景下,路由規則要保證相同請求下,落地在同一個資料庫和同一表中,要不然資料庫主鍵約束就不起效果了,因為是不同的資料庫和表主鍵不相關。


②、redis set 防重很多資料需要處理,只能被處理一次,比如我們可以計算資料的 MD5 將其放入 redis 的 set,每次處理資料,先看這個 MD5 是否已經存在,存在就不處理。


4)防重表

使用訂單號 orderNo 做為去重表的唯一索引,把唯一索引插入去重表,再進行業務操作,且他們在同一個事務中。這個保證了重複請求時,因為去重表有唯一約束,導致請求失敗,避免了冪等問題。這裡要注意的是,去重表和業務表應該在同一庫中,這樣就保證了在同一個事務,即使業務操作失敗了,也會把去重表的資料回滾。這個很好的保證了資料一致性。之前說的 redis 防重也算