Securing REST Services
一般有六種方式實現的REST服務的安全:
Session-based security
HTTP Basic Authentication
Digest Authentication
Certificate based security
XAuth
OAuth
Session-based Security
Session-based Security方式需要server端會話保存用戶的身份信息,以便在多個請求中使用。它的流程圖如下所示:
Spring Security支持此種安全模型,此種方式對於開發者非常有吸引力。但是這種方式違背了REST無狀態的約束,而且因為server需要保存client的狀態,所以這種方式不是可擴展的。理想情況下,client應該保存自己的狀態,而server應該是無狀態的。
HTTP Basic Authentication
當有用戶交互時,提供一個login窗口獲取username和password是可行的,但是服務之間的交互就不可行了。HTTP Basic Authentication可同時支持交互與非交互模式。在這種方法中,當client發出一個針對保護資源的請求,server會返回一個401(Unauthorized)狀態碼和“WWW-Authenticate” header。
GET /protected_resource
401 Unauthorized
WWW-Authenticate: Basic realm="Example Realm"
Basic部分表明使用Basic認證,realm指示服務器上一個保護的空間。
客戶端收到上面的響應后,用Base64編碼"user:password"字符串,並將其放到Authorization header后發送給服務器,如:
GET /protected_resource
Authorization: Basic bHxpY26U5lkjfdk
服務器解碼提交的信息、驗證提交的證書。如果認證成功,server結束此請求。
因為client包含了認證的信息,所以server是無狀態的。但是client指示簡單的對用戶名和密碼進行加密,因此在not-SSL/TLS鏈接中,此種方式有可能遭受中間人攻擊,竊取密碼。
Digest Authentication
Digest Authentication和HTTP Basic Authentication非常相似,除了用戶的證書是加密傳送的。client提交一個針對包含資源的請求,然后server回復一個401(Unauthorized)狀態碼和一個WWW-Authenticate header,如下所示:
GET /protected_resource
401 Unauthorized
WWW-Authenticate: Digest realm="Example Realm", nonce="P35kl89sdfghERT10Asdfnbvc", qop="auth"
WWWW-Authenticate指定了認證模式、server產生的特殊詞語、qop(quality of protection)。nonce是一個任意的token,用於加密。qop指示語可包含"auth"和"auth-int"兩個值:
A qop value "auth" indicates that the digest is used for authentication purposes
A value "auth-int" indicates that digest will be used for authentication and request integrity
client接收到響應后,如果qop是auth,client會用下面公式產生digest(摘要):
hash_value_1 = MD5(username:realm:password)
has_value_2 = MD5(request_method:request_uri)
digest = MD5(hash_value_1:nonce:hash_value_2)
如果qop是auth-int,client在產生digest時會包含request body:
hash_value_1 = MD5(username:realm:password)
has_value_2 = MD5(request_method:request_uri:MD5(request_body))
digest = MD5(hash_value_1:nonce:hash_value_2)
server接收到上面經過計算的digest后,會進行認證操作。如果認證成功,server會結束請求過程。
Digest authentication比HTTP Basic authentication更加安全。但是,在non-SSL/TLS通信中,它還是存在被snooper檢索digest、回復請求的可能。解決這個問題的一個方法就是限制server產生的nonces只能使用一次。還有,由於server為了認證必須產生digest,它需要能夠訪問密碼的明文格式。因此server不能使用不可逆的加密算法,而且server會成為系統安全的薄弱環節。
Certificte-Based Security
Certificated-based security模型需要證書驗證參與者的身份。在SSL/TLS為基礎的通信中,client通過證書驗證server的身份。在這種方式中,當server接收到一個針對保護資源的請求后,會發送自己的證書給client。client確認此證書是可信證書機構頒發的證書后,發送它自己的證書給server。server驗證client的證書,當成功驗證后,server會將受保護資源的訪問權限分給client。
Certificate-based security模型消除了發送共享密碼的需求,使得它更加安全。但是,布置和維護證書是非常昂貴的,一般只能在大型系統中使用。
XAuth
隨着REST API變得流行起來,使用API的第三方應用的數量也會顯著增長。這些應用需要用戶名和密碼和REST服務交互,這樣存在巨大的風險,因為第三方應用有訪問用戶名和密碼的權限。一種簡單的解決方案是第三方應用保存用戶信息。如果用戶更改了他的憑證,他需要更新所有的第三方應用。而且此種方式不允許用戶撤銷他對第三方的授權。在這種情況下,只有更改密碼才能撤銷授權。
XAuth和OAuth提供了用戶不用保存密碼就能訪問受保護資源的方式。在這種方式中,客戶端應用可通過login form請求用戶名和密碼,然后client發送用戶名和密碼到server,server接收到后,驗證client的憑證。如果驗證成功,一個token會返回給client。client可以放棄用戶名和密碼,在本地存儲token。當再訪問受保護資源時,token會被包含在請求中,可用X-Auth-Token完成此目的。token的有效期由實現決定,token可以一直保存直到server刪除它或者token在給定的時間內過期。如果client和REST API都由一個組織開發,那么這種方式可以作為備選方案。
OAuth 2.0
OAuth(Open Authorization)是一個用戶不用保存密碼就可以訪問受保護資源的框架。OAuth在2007年開發出來,於2010年被OAuth2.0取代。OAuth2.0定義了如下四個角色:
Resource Owner-A:可以給予訪問賬戶或者資源的權限的用戶,比如微博的用戶。
Client A:需要獲得訪問用戶資源權限的客戶端應用。
Authorizatin Server:驗證用戶的身份,並發給client一個可以訪問資源的token。
Resource Server:保存受保護資源的服務器。
OAuth 2.0需要在SSL上完成信息交互。
spring安全相關
可在POM文件中包含如下依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>