在討論安全性時(shí),我們的架構(gòu)中還有另外一個(gè)關(guān)鍵元素一Spring Cloud Config Server。事實(shí)上,保護(hù)配置服務(wù)器比保護(hù)發(fā)現(xiàn)服務(wù)更重要。為什么?因?yàn)槲覀兺ǔ?huì)將它們的身份驗(yàn)證憑據(jù)存儲(chǔ)到外部系統(tǒng),甚至還有其他應(yīng)該隱藏的數(shù)據(jù),以防止未經(jīng)授權(quán)的訪問(wèn)和使用。有若干種方法可以正確保護(hù)配置服務(wù)器。開(kāi)發(fā)人員可以配置HTTP基本身份驗(yàn)證、安全SSL連接、加密/解密敏感數(shù)據(jù),或使用之前文章中提到的“使用SpringCloudConfig進(jìn)行分布式配置”中所述的第三方工具,F(xiàn)在來(lái)仔細(xì)看看其中的一些。
為了服務(wù)器能夠安全高效的提供服務(wù),應(yīng)該如何保證配置服務(wù)器安全
加密和解密
在開(kāi)始之前,我們必須下載并安裝Oracle提供的Java Cryptography Extension(JCE)。它由兩個(gè)JAR文件(local policy.jar 和US_ _export_ policyjar) 組成,它們需要覆蓋JRE lib/security目錄中的現(xiàn)有策略文件。
如果存儲(chǔ)在配置服務(wù)器上的遠(yuǎn)程屬性源包含加密數(shù)據(jù),則它們的值應(yīng)以(cipher};為前綴并用引號(hào)括起來(lái)將其指定為YAML文件。.properties 文件不需要包含引號(hào)。如果無(wú)法解密這樣的值,則在前綴為invalid的相同鍵下將其替換為附加值(通常為<n/a>) 。
在上一個(gè)示例中,我們存儲(chǔ)了用于保護(hù)應(yīng)用程序配置設(shè)置中的keystore文件的密碼。將其保存為純文本文件可能不是最好的主意,因而它是加密的第一個(gè)候選者。問(wèn)題是,我們應(yīng)該如何加密它?
為了服務(wù)器能夠安全高效的提供服務(wù),應(yīng)該如何保證配置服務(wù)器安全
幸運(yùn)的是,SpringBoot提供了兩個(gè)可以對(duì)此提供幫助的RESTful端點(diǎn)。
讓我們來(lái)看一看它是如何工作的。首先,我們需要啟動(dòng)一個(gè)配置服務(wù)器實(shí)例。要完成該目標(biāo),最簡(jiǎn)單的方法是激活
--spring.profiles.active-native配置文件,該配置文件使用本地類路徑或文件系統(tǒng)中的屬性源啟動(dòng)服務(wù)器,F(xiàn)在我們可以調(diào)用兩個(gè)POST端點(diǎn)/encrypt和/decrypt。 /encrypt 方法將我們的純文本密碼作為參數(shù)?梢允褂梅聪虿僮/decrypt檢查出結(jié)果,/decrypt操作會(huì)將加密的密碼作為參數(shù)。
$ 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=
這里的加密是使用公鑰完成的,而解密是使用私鑰完成的。因此,如果僅執(zhí)行加密,則只需要在服務(wù)器中提供公鑰。出于測(cè)試目的,可以使用keytool創(chuàng)建KeyStore。 我們之前已經(jīng)創(chuàng)建了一些KeyStore, 因而不會(huì)遇到任何問(wèn)題。生成的文件應(yīng)放在類路徑中,然后使用encrypt.keyStore.*屬性置于config- service配置設(shè)置中。
encrypt:
keyStore :
location: classpath: /config.jks
password: 123456
alias: config
secret: 123456
現(xiàn)在,如果將每個(gè)微服務(wù)的配置設(shè)置移動(dòng)到配置服務(wù)器,則可以加密每個(gè)密碼,如以下示例片段所示。
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
配置客戶端和服務(wù)器的身份驗(yàn)證
Spring Cloud Config Server的身份驗(yàn)證實(shí)現(xiàn)與Eureka 服務(wù)器完全相同。開(kāi)發(fā)人員可以使用基于標(biāo)準(zhǔn)Spring安全機(jī)制的HTTP基本身份驗(yàn)證。首先,需要確保spring-security工件位于類路徑中:然后,應(yīng)該將security .basic enabled設(shè)置為true以啟用安全性,并定義用戶名和密碼。其示例配置設(shè)置如以下代碼片段所示。
security:
basic:
enabled: true
user:
name: admin
password: admin123
還必須在客戶端啟用基本身份驗(yàn)證。它可以通過(guò)兩種不同的方式實(shí)現(xiàn)。第一種方式是通過(guò)配置服務(wù)器URL。
spring:
cloud:
config:
uri: http://admin:adminl23@localhost:8888
第二種方法基于單獨(dú)的usemame和password屬性。
spring:
cloud:
config:
uri: http://localhost:8888
use rname :
admin
password: admin123
如果要設(shè)置SSL身份驗(yàn)證,則需要按照“保證發(fā)現(xiàn)服務(wù)器的安全”中所描述的步驟進(jìn)行操作。使用私鑰和證書生成KeyStore并設(shè)置正確的配置后,開(kāi)發(fā)人員可以運(yùn)行配置服務(wù)器,F(xiàn)在,它將通過(guò)HTTPS公開(kāi)其RESTful API。唯一的區(qū)別在于客戶端的實(shí)現(xiàn)。這是因?yàn)镾pring Cloud Config 使用的是與Spring Cloud Nettlix Eureka 不同的HTTP客戶端。正如你可能猜到的那樣,它利用了RestTemplate, 因?yàn)樗耆窃赟pring Cloud項(xiàng)目中創(chuàng)建的。
為了服務(wù)器能夠安全高效的提供服務(wù),應(yīng)該如何保證配置服務(wù)器安全
要強(qiáng)制客戶端應(yīng)用程序使用雙向SSL身份驗(yàn)證而不是標(biāo)準(zhǔn)的非安全HTTP連接,首先應(yīng)該創(chuàng)建一個(gè)實(shí)現(xiàn)PropertySourceLocator接口的@Configuration bean。在這里,我們可以構(gòu)建一個(gè)使用安全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;
}
}
但是,默認(rèn)情況下,在應(yīng)用程序嘗試與配置服務(wù)器建立連接之前,不會(huì)創(chuàng)建此Bean。要更改此行為,開(kāi)發(fā)人員還應(yīng)在
/src/main/resources/META-INF中創(chuàng)建spring. factories文件,并指定自定義引導(dǎo)程序配置類。
org. springf ramework. cloud . bootstrap . BootstrapConfiguration =
pl.piomin. services.account.SSLConfigServiceBootstrapConfiguration
使用OAuth2進(jìn)行授權(quán)
我們已經(jīng)在微服務(wù)環(huán)境中討論了與身份驗(yàn)證相關(guān)的一些概念和解決方案。前文已經(jīng)演示了微服務(wù)和服務(wù)發(fā)現(xiàn)之間,以及微服務(wù)和配置服務(wù)器之間的基本和SSL身份驗(yàn)證的示例。在服務(wù)間通信中,授權(quán)似乎比身份驗(yàn)證更重要,而身份驗(yàn)證則在系統(tǒng)的邊緣實(shí)現(xiàn)。開(kāi)發(fā)人員有必要了解身份驗(yàn)證和授權(quán)之間的區(qū)別。簡(jiǎn)而言之,身份驗(yàn)證可以驗(yàn)證訪問(wèn)者的身份,而授權(quán)則驗(yàn)證訪問(wèn)者有權(quán)執(zhí)行的操作。
為了服務(wù)器能夠安全高效的提供服務(wù),應(yīng)該如何保證配置服務(wù)器安全
目前,RESTful HTTP API最流行的授權(quán)方法是OAuth2和Java Web令牌(Java Web Tokens, JWT)。它們可以混合在一起,因?yàn)樗鼈儽绕渌鉀Q方案更加互補(bǔ)。Spring可以為OAuth提供商和使用者提供支持。使用Spring Boot和Spring Security OAuth2,開(kāi)發(fā)人員可以快速實(shí)現(xiàn)常見(jiàn)的安全模式,如單點(diǎn)登錄、令牌中繼或令牌交換。但在深入了解有關(guān)這些項(xiàng)目的細(xì)節(jié)以及其他開(kāi)發(fā)細(xì)節(jié)之前,開(kāi)發(fā)人員需要掌握上述解決方案的基本知識(shí)。
OAuth2 簡(jiǎn)介
OAuth2是幾乎所有主要網(wǎng)站目前使用的標(biāo)準(zhǔn),允許通過(guò)共享API訪問(wèn)其資源。它將用戶身份驗(yàn)證委派給存儲(chǔ)用戶憑據(jù)的獨(dú)立服務(wù),并授權(quán)第三方應(yīng)用程序訪問(wèn)有關(guān)用戶賬戶的共享信息。OAuth2用于為用戶提供數(shù)據(jù)訪問(wèn)權(quán)限,同時(shí)保護(hù)其賬戶憑據(jù)。它為Web、桌面和移動(dòng)應(yīng)用程序提供流程。以下是與OAuth2相關(guān)的一些基本術(shù)語(yǔ)和角色。
口資源所有者( Resource Owner) :此角色將控制對(duì)資源的訪問(wèn)。此訪問(wèn)權(quán)限受到授權(quán)范圍的限制。
口授予權(quán)限(Authorization Grant) :授予訪問(wèn)權(quán)限?梢酝ㄟ^(guò)多種方式確認(rèn)訪問(wèn),如授權(quán)代碼、隱式、資源所有者密碼憑據(jù)和客戶端憑據(jù)等。
口資源服務(wù)器 ( Resource Server) :這是一個(gè)服務(wù)器,用于存儲(chǔ)可以使用特殊令牌共享的所有者資源。
口授權(quán)服務(wù)器(Authorization Server) :它管理密鑰、令牌和其他臨時(shí)資源訪問(wèn)代碼的分配。它還必須確保授予相關(guān)用戶訪問(wèn)權(quán)限。
口訪問(wèn)令牌(AccessToken):這是允許訪問(wèn)資源的密鑰。
為了更好地理解這些術(shù)語(yǔ)和角色在實(shí)踐中的作用,請(qǐng)查看圖12.3。 它可視化了使用OAuth協(xié)議的授權(quán)過(guò)程的典型流程。
為了服務(wù)器能夠安全高效的提供服務(wù),應(yīng)該如何保證配置服務(wù)器安全
現(xiàn)在我們來(lái)看一看之前列出的各個(gè)組件之間交互的進(jìn)一步步 驟。應(yīng)用程序請(qǐng)求資源所有者授權(quán),以便能夠訪問(wèn)所請(qǐng)求的服務(wù)。資源發(fā)送授權(quán)作為響應(yīng),然后由應(yīng)用程序?qū)⑵渑c其自身的身份一起發(fā)送至授權(quán)服務(wù)器。授權(quán)服務(wù)器將驗(yàn)證應(yīng)用程序標(biāo)識(shí)的憑據(jù)和授予的權(quán)限,然后再發(fā)送訪問(wèn)令牌。應(yīng)用程序使用接收的訪問(wèn)令牌從資源服務(wù)器請(qǐng)求資源。最后,如果訪問(wèn)令牌有效,則應(yīng)用程序能夠調(diào)用請(qǐng)求服務(wù)。
構(gòu)建授權(quán)服務(wù)器
從單一應(yīng)用程序遷移到微服務(wù)之后,顯而易見(jiàn)的解決方案似乎是通過(guò)創(chuàng)建授權(quán)服務(wù)來(lái)集中授權(quán)工作。使用Spring Boot和Spring Security, 開(kāi)發(fā)人員可以輕松創(chuàng)建、配置和啟動(dòng)授權(quán)服務(wù)器。首先,需要在項(xiàng)目依賴項(xiàng)中包含以下啟動(dòng)器。
<dependency>
<groupId>org . springframework. cloud</groupId>
<artifactId>spring-cloud-starter -oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springf r amework. cloud</groupId>
<artifactId>spring-cloud- starter-security</artifactId>
</ dependency>
使用Spring Boot實(shí)現(xiàn)授權(quán)服務(wù)器模式非常簡(jiǎn)單,只需要使用@EnableAuthorizationServer注解主類或配置類,然后在application.yml 文件中提供security .oauth2 cient.client-id和security, oauth2 client.client-secret屬性。當(dāng)然,這種變體應(yīng)盡可能簡(jiǎn)單,因?yàn)樗x了客戶端詳細(xì)信息服務(wù)的內(nèi)存實(shí)現(xiàn)。
本示例應(yīng)用程序與本章前面的示例位于同一個(gè)存儲(chǔ)庫(kù)(
http:gitub.co/pioin/sample- spring-cloud-security.git)中,但在不同的分支中,即oauth2分支(tps:/github.com/piomin/sample- spring-cloud- scurit/tree/oauth2)。授權(quán)服務(wù)器在auth- service模塊下可用。
以下是auth-service的main類。
@SpringBootApplication
@EnableAuthorizationServer
public class AuthApplication {
public static void main(string[] args) {
new
SpringApplicationBuilder (AuthApplication.class) .web(true) .run(args) ;
}
}
以下是應(yīng)用程序配置設(shè)置的片段。除了客戶端的ID和機(jī)密之外,我們還設(shè)置了默認(rèn)范圍并為整個(gè)項(xiàng)目啟用了基本安全性。
security:
user :
name: root
password: password
oauth2:
client:
client-id: piotr . minkowski
client-secret: 123456
scope:read
運(yùn)行授權(quán)服務(wù)之后,我們就可以執(zhí)行一些測(cè)試。例如,可以調(diào)用POST /auth/token方法,以便使用資源所有者密碼憑據(jù)創(chuàng)建訪問(wèn)令牌,就像在以下命令中一樣。
$ curl piotr . minkowski : 123456@localhost: 9999/oauth/token -d
grant_ type=password -d username root -d password-pas sword
開(kāi)發(fā)人員還可以通過(guò)從Web瀏覽器調(diào)用GET /oauth/authorize 端點(diǎn)來(lái)使用授權(quán)代碼授予類型。
http://localhost:9999/oauth/ authorize?response type=token&
client_ id=piotr . minkowski&redirect uri=http://example 。com&scope=read
之后,開(kāi)發(fā)人員將被重定向到如圖12.4 所示的批準(zhǔn)頁(yè)面。現(xiàn)在可以確認(rèn)操作并最終獲得訪問(wèn)令牌。它將被發(fā)送到初始請(qǐng)求的redirect. _uri 參數(shù)中傳遞的回調(diào)URL。以下是筆者在測(cè)試后收到的示例回復(fù)。
http:/ /example. com/ #access_ token=dd736a4a- 1408-4f3f-b3ca-43dcc05e6df0&
token_ type-bearer&expires_ in=43200.
為了服務(wù)器能夠安全高效的提供服務(wù),應(yīng)該如何保證配置服務(wù)器安全
application.yml文件中提供的相同OAuth2配置也可以按編程的方式實(shí)現(xiàn)。為了達(dá)到這個(gè)目的,開(kāi)發(fā)人員應(yīng)該聲明實(shí)現(xiàn)
AuthorizationServerConfigurer的任何@Beans。其中之一是 AuthorizationServerConfigurerAdapter適配器,它提供了空方法,允許創(chuàng)建以下獨(dú)立配置器的不同定義。
口
ClientDetailServiceConfigurer: 這定義了客戶端詳細(xì)信息服務(wù)?梢猿跏蓟蛻舳嗽敿(xì)信息,也可以只引用現(xiàn)有存儲(chǔ)。
口
AuthorizationServerSecurityConfigurer: 這定義了令牌端點(diǎn)/oauth/token. _key和/oauth/check_ _token 的安全約束。
口
AuthorizationServerEndpointsConfigurer: 這定義了授權(quán)和令牌端點(diǎn)以及令牌服務(wù)。這種授權(quán)服務(wù)器實(shí)現(xiàn)的方法為開(kāi)發(fā)人員提供了更多機(jī)會(huì)。例如,可以使用ID和密碼定義多個(gè)客戶端,如以下代碼片段所示。下文將介紹一些更高級(jí)的示例。
@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);
}
}
必須為授權(quán)服務(wù)器配置的最后一項(xiàng)是 Web安全性。在擴(kuò)展
WebSecuriyConfigurerAdapter的類中,我們定義了內(nèi)存中的用戶憑據(jù)存儲(chǔ)和訪問(wèn)特定資源的權(quán)限,如登錄頁(yè)面。
@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") ;
}
}
客戶端配置
應(yīng)用程序可以使用以兩種不同方法配置的OAuth2 客戶端。第一種方法是通過(guò)@EnableOAuth2Client注解,它將創(chuàng)建一個(gè)ID為oauth2ClientContextFilter的過(guò)濾器bean,負(fù)責(zé)存儲(chǔ)請(qǐng)求和上下文。它還管理應(yīng)用程序和授權(quán)服務(wù)器之間的通信。但是,我們將要討論的卻是第二種方法,即通過(guò)@EnableOAuth2Sso實(shí)現(xiàn)0Auth2客戶端。單點(diǎn)登錄(Single Sign-On,SsO) 是一種眾所周知的安全模式,它允許用戶使用一組登錄憑據(jù)來(lái)訪問(wèn)多個(gè)應(yīng)用程序。此注解提供了兩個(gè)功能一OAuth2 客戶端和身份驗(yàn)證。身份驗(yàn)證功能模塊使開(kāi)發(fā)人員的應(yīng)用程序可以符合典型的Spring Security機(jī)制(如表單登錄)。客戶端模塊則具有與@EnableOAuth2Client提供的功能相同的特性。所以,開(kāi)發(fā)人員可以將@ EnableOAuth2Sso視為比@EnableOAuth2Client更高級(jí)別的注解。
為了服務(wù)器能夠安全高效的提供服務(wù),應(yīng)該如何保證配置服務(wù)器安全
在下面的示例代碼片段中,我們已經(jīng)注解了使用@EnableOAuth2Sso擴(kuò)展
WebSecurityConfigurerAdapter的類。由于此擴(kuò)展,Spring Boot 配置了帶有OAuth2身份驗(yàn)證處理程序的安全過(guò)濾器鏈(Security Filter Chain)。在這種情況下,僅允許對(duì)/login頁(yè)面的請(qǐng)求,而所有其他請(qǐng)求都需要身份驗(yàn)證?梢允褂胹ecurity .oauth2 sso login-path屬性覆蓋表單登錄頁(yè)面路徑。在覆蓋它之后,開(kāi)發(fā)人員還應(yīng)該記得在WebSecurityConfig中更改路徑模式。
@Configuration
@EnableOAuth2Sso
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure (HttpSecurity http) throws Exception {
http.antMatcher("/**)
. authorizeRequests ()
. antMatchers("/login**")
.permitAll ()
. anyRequest ()
. authenticated() ;
還有一些需要設(shè)置的配置設(shè)置。首先,應(yīng)該禁用基本身份驗(yàn)證,因?yàn)槲覀円呀?jīng)啟用了表單登錄方法和@EnableOAuth2Sso注解。然后,必須提供一些基本的OAuth2客戶端屬性,如客戶端憑據(jù)和授權(quán)服務(wù)器公開(kāi)的HTTPAPI端點(diǎn)的地址。
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文件片段中的最后一個(gè)屬性是security .oauth2. resource.userInfoUri,它需要服務(wù)器端的其他端點(diǎn)。通過(guò)UserController 實(shí)現(xiàn)的端點(diǎn)將返回java.security Principal對(duì)象,指示當(dāng)前經(jīng)過(guò)身份驗(yàn)證的用戶。
@RestController
public class UserController {
eRequestMapping (" /user")
public Principal user (Principal user) {
return user;
}
}
現(xiàn)在,如果調(diào)用由我們的某個(gè)微服務(wù)公開(kāi)的任何端點(diǎn),都將自動(dòng)重定向到登錄頁(yè)面。由于我們?yōu)閮?nèi)存客戶端的詳細(xì)信息存儲(chǔ)設(shè)置了autoApprove選項(xiàng),因而將自動(dòng)生成授予的權(quán)限和訪問(wèn)令牌,而無(wú)須用戶進(jìn)行任何交互。在登錄頁(yè)面提供憑據(jù)后,開(kāi)發(fā)人員應(yīng)該從請(qǐng)求的資源處獲得響應(yīng)。