保證配置服務器的安全
在討論安全性時,我們的架構中還有另外一個關鍵元素一Spring Cloud Config Server。事實上,保護配置服務器比保護發現服務更重要。為什么?因為我們通常會將它們的身份驗證憑據存儲到外部系統,甚至還有其他應該隱藏的數據,以防止未經授權的訪問和使用。有若干種方法可以正確保護配置服務器。開發人員可以配置HTTP基本身份驗證、安全SSL連接、加密/解密敏感數據,或使用之前文章中提到的“使用SpringCloudConfig進行分布式配置”中所述的第三方工具?,F在來仔細看看其中的一些。
加密和解密
在開始之前,我們必須下載并安裝Oracle提供的Java Cryptography Extension(JCE)。它由兩個JAR文件(local policy.jar 和US_ _export_ policyjar) 組成,它們需要覆蓋JRE lib/security目錄中的現有策略文件。
如果存儲在配置服務器上的遠程屬性源包含加密數據,則它們的值應以(cipher};為前綴并用引號括起來將其指定為YAML文件。.properties 文件不需要包含引號。如果無法解密這樣的值,則在前綴為invalid的相同鍵下將其替換為附加值(通常為
在上一個示例中,我們存儲了用于保護應用程序配置設置中的keystore文件的密碼。將其保存為純文本文件可能不是最好的主意,因而它是加密的第一個候選者。問題是,我們應該如何加密它?
幸運的是,SpringBoot提供了兩個可以對此提供幫助的RESTful端點。
讓我們來看一看它是如何工作的。首先,我們需要啟動一個配置服務器實例。要完成該目標,最簡單的方法是激活
--spring.profiles.active-native配置文件,該配置文件使用本地類路徑或文件系統中的屬性源啟動服務器?,F在我們可以調用兩個POST端點/encrypt和/decrypt。 /encrypt 方法將我們的純文本密碼作為參數。可以使用反向操作/decrypt檢查出結果,/decrypt操作會將加密的密碼作為參數。
$ curl http://localhost:8888/encrypt -d 123456
AQAzI8jv26K3n6ff+iFzQA9DUpWmg7 9emWu4ndEXyvjYnKFSG7 rBmJP0oFTb8RzjZbTwt4
ehRiKWqu5qXkH8SAv/ 8mr2kdwB28kfVvPj/Ib5hdUkH1TVrylcnpZaKaQYBaxlsaORWAKQ
Dk8MQKRw1nJ5HM4LY9yjda0YQFNYAy0/KRnwUFihiV5xDk51MOiG4b77AVLmz+9aSAODKL
057wOQUzM1 tSA7109HyDQW2Hz11q93u0CaP5VQLCJAjmHcHvh1vM442bU3B2 9JNjH+2nFS
ORhEyUvpUqzo+PBi 4ROAKJH9XZ8G7RaTOeWIcJhentKRfOU/EgWIVW21NpsE2 9BHwf4F2J
ZiWY2 +WqcHuHk367X21vk11AV19tJk9aUVNRk=
這里的加密是使用公鑰完成的,而解密是使用私鑰完成的。因此,如果僅執行加密,則只需要在服務器中提供公鑰。出于測試目的,可以使用keytool創建KeyStore。 我們之前已經創建了一些KeyStore, 因而不會遇到任何問題。生成的文件應放在類路徑中,然后使用encrypt.keyStore.*屬性置于config- service配置設置中。
encrypt:
keyStore :
location: classpath: /config.jks
password: 123456
alias: config
secret: 123456
現在,如果將每個微服務的配置設置移動到配置服務器,則可以加密每個密碼,如以下示例片段所示。
server :
port: S{PORT:8091 }
ssl:
enabled: true
key-store: classpath:account.jks
key-store-password:
'{cipher }AQAzI8jv26K3n6ff+iFzQA9DUpWmg7 9emWu4ndEXyvj YnKFSG7 rBmJPOoFTb
8RzjZbTwt4ehRiKWqu5qXKH8SAv/ Bmr2kdwB28kfVvPj/ Lb5hdUkH1TVry1cnpZaKaQYBa
xlsa0RMAKQDk8MQKRw1nJ5HM4LY9yjdaOYQFNYAy0/KRnWUFihiV5xDk51MOiG4b77AVLm
z+9aSA0DKL057wOQUzM1 tSA7109HyDQW2Hz 11q93uOCa P5VQLCJAjmHcHvh1vM4 42bU3B2
9JNjH+ 2nFS0RhEyUvpUqzo+PBi 4ROAKJH9XZ8G7RaTOeWI cJhentKRfOU/EgWIVW2 lNpsE
29BHwf4F2JZiWY2+WqCHuHk367X21vk11AV19tJk9aUVNRK-,
key-alias: account
配置客戶端和服務器的身份驗證
Spring Cloud Config Server的身份驗證實現與Eureka 服務器完全相同。開發人員可以使用基于標準Spring安全機制的HTTP基本身份驗證。首先,需要確保spring-security工件位于類路徑中:然后,應該將security .basic enabled設置為true以啟用安全性,并定義用戶名和密碼。其示例配置設置如以下代碼片段所示。
security:
basic:
enabled: true
user:
name: admin
password: admin123
還必須在客戶端啟用基本身份驗證。它可以通過兩種不同的方式實現。第一種方式是通過配置服務器URL。
spring:
cloud:
config:
uri: http://admin:adminl23@localhost:8888
第二種方法基于單獨的usemame和password屬性。
spring:
cloud:
config:
uri: http://localhost:8888
use rname :
admin
password: admin123
如果要設置SSL身份驗證,則需要按照“保證發現服務器的安全”中所描述的步驟進行操作。使用私鑰和證書生成KeyStore并設置正確的配置后,開發人員可以運行配置服務器。現在,它將通過HTTPS公開其RESTful API。唯一的區別在于客戶端的實現。這是因為Spring Cloud Config 使用的是與Spring Cloud Nettlix Eureka 不同的HTTP客戶端。正如你可能猜到的那樣,它利用了RestTemplate, 因為它完全是在Spring Cloud項目中創建的。
要強制客戶端應用程序使用雙向SSL身份驗證而不是標準的非安全HTTP連接,首先應該創建一個實現PropertySourceLocator接口的@Configuration bean。在這里,我們可以構建一個使用安全HTTP連接工廠的自定義RestTemplate.
@Configuration
public class ssLConfigSe rviceBootstrapConfiguration {
@Autowired
ConfigClientProperties properties;
@Bean
public ConfigServicePropertySourceLocator
configServicePropertySourceLocator() throws Exception {
final char[] password="123456" . toCharArray();
final File keyStoreFile=new
File ("src/main/ resources/discovery.jks");
SSLContext sslContext=SSLContexts . custom()
. loadKeyMaterial (keyStoreFile, password, password)
.loadTrustMaterial (keyStoreFile) .build() ;
CloseableHttpClient httpClient -
HttpClients . custom() . setssLContext (sslContext) .build() ;
HttpComponentsClienthttpRequestFactory requestFactory new
HttpComponentsClientHttpRequestFactory (httpClient) ;
ConfigServicePropertySourceLocator
configServicePropertySourceLocator=new
ConfigServicePropertySourceLocator (properties) ;
configServicePropertySourceLocator . setRestTemplate (new
RestTemplate (requestFactory) ) ;
return configServicePropertySourceLocator;
}
}
但是,默認情況下,在應用程序嘗試與配置服務器建立連接之前,不會創建此Bean。要更改此行為,開發人員還應在
/src/main/resources/META-INF中創建spring. factories文件,并指定自定義引導程序配置類。
org. springf ramework. cloud . bootstrap . BootstrapConfiguration=
pl.piomin. services.account.SSLConfigServiceBootstrapConfiguration
使用OAuth2進行授權
我們已經在微服務環境中討論了與身份驗證相關的一些概念和解決方案。前文已經演示了微服務和服務發現之間,以及微服務和配置服務器之間的基本和SSL身份驗證的示例。在服務間通信中,授權似乎比身份驗證更重要,而身份驗證則在系統的邊緣實現。開發人員有必要了解身份驗證和授權之間的區別。簡而言之,身份驗證可以驗證訪問者的身份,而授權則驗證訪問者有權執行的操作。
目前,RESTful HTTP API最流行的授權方法是OAuth2和Java Web令牌(Java Web Tokens, JWT)。它們可以混合在一起,因為它們比其他解決方案更加互補。Spring可以為OAuth提供商和使用者提供支持。使用Spring Boot和Spring Security OAuth2,開發人員可以快速實現常見的安全模式,如單點登錄、令牌中繼或令牌交換。但在深入了解有關這些項目的細節以及其他開發細節之前,開發人員需要掌握上述解決方案的基本知識。
OAuth2 簡介
OAuth2是幾乎所有主要網站目前使用的標準,允許通過共享API訪問其資源。它將用戶身份驗證委派給存儲用戶憑據的獨立服務,并授權第三方應用程序訪問有關用戶賬戶的共享信息。OAuth2用于為用戶提供數據訪問權限,同時保護其賬戶憑據。它為Web、桌面和移動應用程序提供流程。以下是與OAuth2相關的一些基本術語和角色。
口資源所有者( Resource Owner) :此角色將控制對資源的訪問。此訪問權限受到授權范圍的限制。
口授予權限(Authorization Grant) :授予訪問權限。可以通過多種方式確認訪問,如授權代碼、隱式、資源所有者密碼憑據和客戶端憑據等。
口資源服務器 ( Resource Server) :這是一個服務器,用于存儲可以使用特殊令牌共享的所有者資源。
口授權服務器(Authorization Server) :它管理密鑰、令牌和其他臨時資源訪問代碼的分配。它還必須確保授予相關用戶訪問權限。
口訪問令牌(AccessToken):這是允許訪問資源的密鑰。
為了更好地理解這些術語和角色在實踐中的作用,請查看圖12.3。 它可視化了使用OAuth協議的授權過程的典型流程。
現在我們來看一看之前列出的各個組件之間交互的進一步步 驟。應用程序請求資源所有者授權,以便能夠訪問所請求的服務。資源發送授權作為響應,然后由應用程序將其與其自身的身份一起發送至授權服務器。授權服務器將驗證應用程序標識的憑據和授予的權限,然后再發送訪問令牌。應用程序使用接收的訪問令牌從資源服務器請求資源。最后,如果訪問令牌有效,則應用程序能夠調用請求服務。
構建授權服務器
從單一應用程序遷移到微服務之后,顯而易見的解決方案似乎是通過創建授權服務來集中授權工作。使用Spring Boot和Spring Security, 開發人員可以輕松創建、配置和啟動授權服務器。首先,需要在項目依賴項中包含以下啟動器。
dependency>
使用Spring Boot實現授權服務器模式非常簡單,只需要使用@EnableAuthorizationServer注解主類或配置類,然后在application.yml 文件中提供security .oauth2 cient.client-id和security, oauth2 client.client-secret屬性。當然,這種變體應盡可能簡單,因為它定義了客戶端詳細信息服務的內存實現。
本示例應用程序與本章前面的示例位于同一個存儲庫(
http:gitub.co/pioin/sample- spring-cloud-security.git)中,但在不同的分支中,即oauth2分支(
tps:/github.com/piomin/sample- spring-cloud- scurit/tree/oauth2)。授權服務器在auth- service模塊下可用。
以下是auth-service的main類。
@SpringBootApplication
服務器@EnableAuthorizationServer
public class AuthApplication {
public static void main(string[] args) {
new
SpringApplicationBuilder (AuthApplication.class) .web(true) .run(args) ;
}
}
以下是應用程序配置設置的片段。除了客戶端的ID和機密之外,我們還設置了默認范圍并為整個項目啟用了基本安全性。
security:
user :
name: root
password: password
oauth2:
client:
client-id: piotr . minkowski
client-secret: 123456
scope:read
運行授權服務之后,我們就可以執行一些測試。例如,可以調用POST /auth/token方法,以便使用資源所有者密碼憑據創建訪問令牌,就像在以下命令中一樣。
$ curl piotr . minkowski : 123456@localhost: 9999/oauth/token -d
grant_ type=password -d username root -d password-pas sword
開發人員還可以通過從Web瀏覽器調用GET /oauth/authorize 端點來使用授權代碼授予類型。
http://localhost:9999/oauth/ authorize?response type=token&
client_ id=piotr . minkowski&redirect uri=http://example 。com&scope=read
之后,開發人員將被重定向到如圖12.4 所示的批準頁面?,F在可以確認操作并最終獲得訪問令牌。它將被發送到初始請求的redirect. 配置 _uri 參數中傳遞的回調URL。以下是筆者在測試后收到的示例回復。
http:/ /example. com/ #access_ token=dd736a4a- 1408-4f3f-b3ca-43dcc05e6df0&
token_ type-bearer&expires_ in=43200.
安全
application.yml文件中提供的相同OAuth2配置也可以按編程的方式實現。為了達到這個目的,開發人員應該聲明實現
AuthorizationServerConfigurer的任何@Beans。其中之一是
AuthorizationServerConfigurerAdapter適配器,它提供了空方法,允許創建以下獨立配置器的不同定義。
口
ClientDetailServiceConfigurer: 這定義了客戶端詳細信息服務??梢猿跏蓟蛻舳嗽敿毿畔?,也可以只引用現有存儲。
口
AuthorizationServerSecurityConfigurer: 這定義了令牌端點/oauth/token. _key和/oauth/check_ _token 的安全約束。
口
AuthorizationServerEndpointsConfigurer: 這定義了授權和令牌端點以及令牌服務。這種授權服務器實現的方法為開發人員提供了更多機會。例如,可以使用ID和密碼定義多個客戶端,如以下代碼片段所示。下文將介紹一些更高級的示例。
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends Authori zati onSe rverConfigurerAdapter
{
@override
public void conf igure (AuthorizationServersecurityConfigurer
oauthServer) throws Exception {
oauthServer
. tokenKeyAccess ("permitA1l()")
. checkTokenAccess (" isAuthenticated()");
}
@Override
public void configure (ClientDetailsServiceConfigurer clients) throws
Exception {
clients . inMemory()
. withClient ("piotr . minkowski") .secret ("123456")
.scopes ("read")
.authorities ("ROLE CLIENT")
.authorizedGrantTypes ("authorization code" ,
"refresh_ token", "implicit")
. autoApprove (true)
.and( )
.withClient ("john. smith") .secret ("123456")
.scopes ("read", "write")
. authorities ("ROLE CLIENT")
. authorizedGrantTypes ("authorization code",
"refresh_ token", "implicit")
.autoApprove (true);
}
}
必須為授權服務器配置的最后一項是 Web安全性。在擴展
WebSecuriyConfigurerAdapter的類中,我們定義了內存中的用戶憑據存儲和訪問特定資源的權限,如登錄頁面。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter (
@Autowired
private AuthenticationManager authenticationManager ;
@Override
protected void configure (HttpSecurity http) throws Exception {
http. requestMatchers( )
. antMatchers ("/login", "/oauth/authorize")
.and( )
.authorizeRequests ()
. anyRequest () . authenticated()
.and ()
.formLogin() .permitAll ();
}
@Override
protected void configure (AuthenticationManagerBuilder auth) throws
Exception {
auth. parentAuthenticationManager (authenticat ionManager)
. inMemoryAuthentication()
.withUser ("piotr . minkowski") .password ("123456")
. roles ("USERS") ;
}
}
客戶端配置
應用程序可以使用以兩種不同方法配置的OAuth2 客戶端。第一種方法是通過@EnableOAuth2Client注解,它將創建一個ID為oauth2ClientContextFilter的過濾器bean,負責存儲請求和上下文。它還管理應用程序和授權服務器之間的通信。但是,我們將要討論的卻是第二種方法,即通過@EnableOAuth2Sso實現0Auth2客戶端。單點登錄(Single Sign-On,SsO) 是一種眾所周知的安全模式,它允許用戶使用一組登錄憑據來訪問多個應用程序。此注解提供了兩個功能一OAuth2 客戶端和身份驗證。身份驗證功能模塊使開發人員的應用程序可以符合典型的Spring Security機制(如表單登錄)??蛻舳四K則具有與@EnableOAuth2Client提供的功能相同的特性。所以,開發人員可以將@ EnableOAuth2Sso視為比@EnableOAuth2Client更高級別的注解。
在下面的示例代碼片段中,我們已經注解了使用@EnableOAuth2Sso擴展
WebSecurityConfigurerAdapter的類。由于此擴展,Spring Boot 配置了帶有OAuth2身份驗證處理程序的安全過濾器鏈(Security Filter Chain)。在這種情況下,僅允許對/login頁面的請求,而所有其他請求都需要身份驗證??梢允褂胹ecurity .oauth2 sso login-path屬性覆蓋表單登錄頁面路徑。在覆蓋它之后,開發人員還應該記得在WebSecurityConfig中更改路徑模式。
@Configuration
@EnableOAuth2Sso
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure (HttpSecurity http) throws Exception {
http.antMatcher("/**)
. authorizeRequests ()
. antMatchers("/login**")
.permitAll ()
. anyRequest ()
. authenticated() ;
還有一些需要設置的配置設置。首先,應該禁用基本身份驗證,因為我們已經啟用了表單登錄方法和@EnableOAuth2Sso注解。然后,必須提供一些基本的OAuth2客戶端屬性,如客戶端憑據和授權服務器公開的HTTPAPI端點的地址。
security:
basie:
enabled: false
oauth2:
client:
clientId: piotr .minkowski
clientSecret: 123456
accessTokenUri: http://localhost :9999/oauth/token
userAuthorizationUri: http://loca1host:9999/oauth/authorize
resource:
userInfoUri: http://localhost: 9999/user
application.yml文件片段中的最后一個屬性是security .oauth2. resource.userInfoUri,它需要服務器端的其他端點。通過UserController 實現的端點將返回java.security Principal對象,指示當前經過身份驗證的用戶。
@RestController
public class UserController {
eRequestMapping (" /user")
public Principal user (Principal user) {
return user;
}
}
現在,如果調用由我們的某個微服務公開的任何端點,都將自動重定向到登錄頁面。由于我們為內存客戶端的詳細信息存儲設置了autoApprove選項,因而將自動生成授予的權限和訪問令牌,而無須用戶進行任何交互。在登錄頁面提供憑據后,開發人員應該從請求的資源處獲得響應。
本文給大家講解的內容是保證配置服務器的安全下篇文章給大家講解的是使用JDBC后端存儲;覺得文章不錯的朋友可以轉發此文關注小編,有需要的可以私信小編獲取資料;感謝大家的支持!
版權聲明:本文來自互聯網整理發布,如有侵權,聯系刪除
原文鏈接:http://www.freetextsend.comhttp://www.freetextsend.com/qingganjiaoliu/15173.html