通常有六種方式實現的REST服務的安全:算法
Session-based security HTTP Basic Authentication Digest Authentication Certificate based security XAuth OAuth
Session-based Security方式須要server端會話保存用戶的身份信息,以便在多個請求中使用。它的流程圖以下所示:spring
Spring Security支持此種安全模型,此種方式對於開發者很是有吸引力。可是這種方式違背了REST無狀態的約束,並且由於server須要保存client的狀態,因此這種方式不是可擴展的。理想狀況下,client應該保存本身的狀態,而server應該是無狀態的。安全
當有用戶交互時,提供一個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指示服務器上一個保護的空間。session
客戶端收到上面的響應後,用Base64編碼"user:password"字符串,並將其放到Authorization header後發送給服務器,如:併發
GET /protected_resource Authorization: Basic bHxpY26U5lkjfdk
服務器解碼提交的信息、驗證提交的證書。若是認證成功,server結束此請求。框架
由於client包含了認證的信息,因此server是無狀態的。可是client指示簡單的對用戶名和密碼進行加密,所以在not-SSL/TLS連接中,此種方式有可能遭受中間人攻擊,竊取密碼。spring-boot
Digest Authentication和HTTP Basic Authentication很是類似,除了用戶的證書是加密傳送的。client提交一個針對包含資源的請求,而後server回覆一個401(Unauthorized)狀態碼和一個WWW-Authenticate header,以下所示:oop
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會成爲系統安全的薄弱環節。
Certificated-based security模型須要證書驗證參與者的身份。在SSL/TLS爲基礎的通訊中,client經過證書驗證server的身份。在這種方式中,當server接收到一個針對保護資源的請求後,會發送本身的證書給client。client確認此證書是可信證書機構頒發的證書後,發送它本身的證書給server。server驗證client的證書,當成功驗證後,server會將受保護資源的訪問權限分給client。
Certificate-based security模型消除了發送共享密碼的需求,使得它更加安全。可是,佈置和維護證書是很是昂貴的,通常只能在大型系統中使用。
隨着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(Open Authorization)是一個用戶不用保存密碼就能夠訪問受保護資源的框架。OAuth在2007年開發出來,於2010年被OAuth2.0取代。OAuth2.0定義了以下四個角色:
Resource Owner-A:能夠給予訪問帳戶或者資源的權限的用戶,好比微博的用戶。 Client A:須要得到訪問用戶資源權限的客戶端應用。 Authorizatin Server:驗證用戶的身份,併發給client一個能夠訪問資源的token。 Resource Server:保存受保護資源的服務器。
OAuth 2.0須要在SSL上完成信息交互。
可在POM文件中包含以下依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>