javascript
通过OAuth 2.0和Okta使用安全的服务器到服务器通信构建Spring Boot应用
“我喜歡編寫身份驗證和授權代碼。” ?從來沒有Java開發人員。 厭倦了一次又一次地建立相同的登錄屏幕? 嘗試使用Okta API進行托管身份驗證,授權和多因素身份驗證。
大多數OAuth 2.0指南都圍繞用戶的上下文,即使用Google,Github,Okta等登錄到應用程序,然后代表該用戶執行某些操作。 盡管有用,但這些指南會忽略沒有用戶且只有一項服務連接到另一項服務的服務器到服務器的通信。 值得慶幸的是,Okta也在此方面為應用程序安全領域提供了幫助。
OAuth 2.0客戶端憑據授予類型專門用于不存在用戶(CRON作業,計劃任務,其他數據工作負載等)的情況。 由于沒有最終用戶或瀏覽器需要處理,因此與其他OAuth流相比,此流的顯示效果不那么出色,但與以用戶為中心的更為復雜的OAuth 2.0授予類型相比,該流更易于理解。 在本教程中,我們將介紹OAuth 2.0客戶端憑據授予類型,以及如何在Spring Boot中部署它以實現安全的服務器間通信。
OAuth 2.0客戶端憑據授予
客戶端憑據授予的目標是允許兩臺計算機安全地通信。 在這種授予類型中,您有一個客戶端(將其視為您的應用程序)向另一個服務(這是您的資源服務器)發出API請求。
為了幫助說明為什么此流程很重要,讓我們退后一步,談談在OAuth 2.0之前所做的工作。
注意 :如果您是OAuth專業人士,則可以跳到下面的代碼示例,或在GitHub上查看示例。
在OAuth 2.0之前,開發人員處理服務器到服務器身份驗證的方式是使用HTTP Basic Auth。 從本質上講,這歸結為開發人員將在每次請求時通過服務器的唯一用戶名和密碼(通常稱為ID和機密)發送。 然后,API服務將通過連接到用戶存儲(數據庫,LDAP等)來驗證每個用戶名和密碼,以驗證憑據。
這種方法有一些缺點和暴露點:
- 上圖中的每個應用程序都處理用戶名和密碼
- 可能需要第二個用戶名和密碼才能連接到用戶存儲
- 每個請求使用相同的用戶名和密碼
有多種方法可以幫助減輕這些風險,但這超出了本文的范圍。
OAuth 2.0客戶端憑據授予被創建來幫助解決HTTP Basic Auth所遇到的問題。 盡管客戶端仍使用用戶名和密碼(稱為client_id和client_secret ),但不是將它們根據每個請求直接發送到API服務,而是通過授權服務器將其交換為令牌。
授權服務器返回一個臨時訪問令牌(使用該令牌直到到期)。 然后,客戶端在與資源服務器進行通信時使用此訪問令牌,這意味著每個有效期僅在網絡上共享一次客戶端最敏感的數據(標識和機密),從而大大降低了遭受破壞的可能性。 一旦資源服務器收到帶有訪問令牌的傳入請求,它將通過與授權服務器進行對話來驗證令牌。
在本文的結尾,我將討論幾種進一步減少網絡呼叫數量的方法,但首先舉一個例子!
讓我們構建一個OAuth 2.0客戶端憑據應用程序!
聊夠了,讓我們做點什么! 我將向您展示如何使用兩個應用程序( client和server通過Spring實現客戶端憑據授予類型。 服務器將具有單個端點,該端點將返回“每日消息”。 客戶端將是一個簡單的命令行應用程序; 您可以輕松地將其替換為后端Web應用程序,CRON作業或任何其他后端腳本。
設置您的授權服務器
為簡單起見,您將使用Okta創建OAuth 2.0授權服務器。 這將處理上面提到的所有客戶端憑據授予內容。 您需要使用Okta嗎? 一點也不! 您可以使用任何需要的OAuth 2.0兼容服務器-但由于我們的服務是免費且易于使用的,因此可以加快此過程。
如果您還沒有免費的開發者帳戶,請轉到developer.okta.com ,然后單擊注冊。 完成后,您將獲得兩條信息,您的Okta基本URL如下所示: dev-123456.oktapreview.com ,以及一封有關如何激活帳戶的說明的電子郵件。
激活帳戶后,仍然在Okta開發者控制臺中,然后需要創建一個應用程序和一個自定義OAuth范圍。 該應用程序將為您提供客戶端ID和密碼,而自定義范圍將您的訪問令牌限制為該示例。
單擊應用程序菜單項,然后單擊添加應用程序 ,然后單擊服務 -> 下一步 。 將名稱更改為您想要的名稱(我將使用“我的MOD應用”),然后單擊完成 。
下一步需要客戶端ID和客戶端機密值。
接下來,為您的應用程序創建一個自定義范圍 。
從菜單欄中選擇API- > Authorization Servers 。 記住發行者的URI值; 您將在下一步中使用它。 通過單擊編輯鉛筆來編輯授權服務器,然后單擊范圍 -> 添加范圍 。 用custom_mod填寫名稱字段,然后按Create 。
有趣的東西!
創建資源服務器
該資源服務器(又稱API服務)將過于簡單,由一個/mod端點組成。 在命令行上使用Spring Initializer創建一個新項目:
curl https://start.spring.io/starter.tgz \-d artifactId=creds-example-server \-d dependencies=security,web \-d language=java \-d type=maven-project \-d baseDir=creds-example-server \ | tar -xzvf -# change into the new directory cd creds-example-server您還需要手動將另外一個依賴項添加到pom.xml :
<dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.0.0.RELEASE</version> </dependency>注意 :我還將DemoApplication重命名為ServerApplication因為我們將很快創建另一個應用程序。
更新ServerApplication以包含@EnableResourceServer批注并添加一個簡單的REST控制器:
@EnableResourceServer @SpringBootApplication public class ServerApplication {public static void main(String[] args) {SpringApplication.run(ServerApplication.class, args);}/*** Allows for @PreAuthorize annotation processing.*/@EnableGlobalMethodSecurity(prePostEnabled = true)protected static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {@Overrideprotected MethodSecurityExpressionHandler createExpressionHandler() {return new OAuth2MethodSecurityExpressionHandler();}}@RestControllerpublic class MessageOfTheDayController {@GetMapping("/mod")@PreAuthorize("#oauth2.hasScope('custom_mod')")public String getMessageOfTheDay(Principal principal) {return "The message of the day is boring for user: " + principal.getName();}} }現在是時候配置應用程序了! 我將application.properties文件重命名為application.yml并將其更新為包括:
security:oauth2:client:clientId: {client-id-from-above}clientSecret: {client-secret-from-above}resource:tokenInfoUri: {issuer-uri-from-above}/v1/introspect就是這樣:幾行代碼和幾行配置! Spring Boot將自動處理訪問令牌的驗證,您只需要擔心代碼。
啟動它并使其運行:
./mvn spring-boot:run如果需要,您可以嘗試訪問http://localhost:8080/mod ,它將以HTTP 401 UNAUTHORIZED響應。
創建OAuth 2.0客戶端
接下來,您將創建一個簡單的命令行客戶端(您可以在任何類型的應用程序中輕松復制此邏輯)。
打開一個新的終端窗口,并使用Spring Initializer創建第二個應用程序:
curl https://start.spring.io/starter.tgz \-d artifactId=creds-example-client \-d dependencies=security \-d language=java \-d type=maven-project \-d baseDir=creds-example-client \ | tar -xzvf -# change into the new directory cd creds-example-client與之前相同,在您的pom.xml添加Spring OAuth 2.0庫作為依賴項:
<dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.0.0.RELEASE</version> </dependency>這次,我將從定義配置開始(再次將application.properties重命名為application.yml ):
example:baseUrl: http://localhost:8080oauth2:client:grantType: client_credentialsclientId: {client-id-from-above}clientSecret: {client-secret-from-above}accessTokenUri: {issuer-uri-from-above}/v1/tokenscope: custom_mod我已在example下為配置命名空間,因為您可以連接到多個服務器。
我配置了一些屬性:
- baseUrl是示例服務器的基本URL
- grantType定義連接的授予類型
- clientId和clientSecret與上述相同
- accessTokenUri定義用于獲取訪問令牌的URI
- scope是我們在上面創建的自定義范圍
最后是我們的ClientApplication (從DemoApplication重命名):
@SpringBootApplication public class ClientApplication implements CommandLineRunner {private final Logger logger = LoggerFactory.getLogger(ClientApplication.class);@Value("#{ @environment['example.baseUrl'] }")private String serverBaseUrl;public static void main(String[] args) {SpringApplication.run(ClientApplication.class, args);}@Bean@ConfigurationProperties("example.oauth2.client")protected ClientCredentialsResourceDetails oAuthDetails() {return new ClientCredentialsResourceDetails();}@Beanprotected RestTemplate restTemplate() {return new OAuth2RestTemplate(oAuthDetails());}@Overridepublic void run(String... args) {logger.info("MOD: {}", restTemplate().getForObject(serverBaseUrl + "/mod", String.class));} }我想談談幾件事:
- CommandLineRunner界面添加了一個run方法,該方法在初始化后自動被調用,應用程序在退出該方法后退出
- 我創建了一個ClientCredentialsResourceDetails bean,該bean綁定到我的配置屬性: example.oauth2.client
- 我使用OAuth2RestTemplate代替標準的RestTemplate它自動管理所有OAuth 2.0訪問令牌交換并設置Authentication: Bearer標頭值。 基本上,它可以處理所有OAuth詳細信息,因此您無需擔心其中任何一個!
使用./mvnw spring-boot:run運行該應用程序,您應該看到類似于以下內容的控制臺輸出:
2018-03-20 12:56:10.058 INFO 15833 --- [main] c.e.c.ClientApplication: MOD: The message of the day is boring for user: 0oabcd12yz2EpHuis75s3客戶端已成功與服務器通信! 還不錯吧? 在短短的幾行代碼中,您就可以設置OAuth 2.0授權服務器并進行配置,還可以創建兩個Spring應用程序(一個客戶端和一個服務器),現在可以使用OAuth 2.0客戶端憑據授予類型安全地進行通信!
注意:如果您看到401或500異常,請再次檢查您的application.yml配置文件是否包含正確的信息。
額外的功勞:減少對授權服務器的呼叫次數
上面的第二個序列圖似乎比第一個更復雜,即使考慮到訪問令牌的重用也是如此。 訪問令牌是不透明的,它們后面沒有任何規范,格式由授權服務器實現。
在Okta,我們使用簽名的JWT,這意味著您可以在本地對其進行驗證,而不是根據每個請求從API服務向授權服務器提出額外的請求。
我們有幾種不同語言的幫助程序庫和一個Spring Boot入門程序 ,它將為您處理本地驗證。
注意:在撰寫本文時, okta-spring-boot僅適用于Spring Boot 1.5.x,請參見GitHub上的示例
進一步了解OAuth 2.0和Okta
在這篇文章中,我已經解釋了OAuth 2.0客戶端憑據授予類型,并創建了用于執行此流程的小型演示應用程序(使用Spring Boot,只需很少的代碼!)。 如果您有任何疑問,請將其留在下面或在Twitter上ping我( @briandemers )或@OktaDev 。
有關OAuth 2.0和Okta的更多信息,請查看以下資源:
- OAuth到底是什么?
- OAuth.com
- 使用Spring Boot和OAuth保護您的SPA
使用Spring Boot和OAuth 2.0進行安全的服務器到服務器通信最初于2018年4月2日發布在Okta開發者博客上。
“我喜歡編寫身份驗證和授權代碼。” ?從來沒有Java開發人員。 厭倦了一次又一次地建立相同的登錄屏幕? 嘗試使用Okta API進行托管身份驗證,授權和多因素身份驗證。
翻譯自: https://www.javacodegeeks.com/2018/06/spring-boot-server-to-server-communication-okta.html
總結
以上是生活随笔為你收集整理的通过OAuth 2.0和Okta使用安全的服务器到服务器通信构建Spring Boot应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机怎么打开php文件(php是什么格式
- 下一篇: spring vaadin_在Sprin