使用UAA OAuth2授权服务器–客户端和资源
在上一篇文章中,我介紹了如何使用Cloud Foundry UAA項(xiàng)目啟動(dòng)OAuth2授權(quán)服務(wù)器,以及如何使用OAuth2授權(quán)代碼流程中涉及的一些參與者來(lái)填充它。
我已經(jīng)在Digital Ocean網(wǎng)站上找到了這篇文章,在描述OAuth2授權(quán)代碼流方面做得非常好,因此,與其重新哈希該流中涉及的內(nèi)容,我不如直接使用Spring Boot / Spring Security來(lái)實(shí)現(xiàn)該流。
下圖受此處的啟發(fā),顯示了授權(quán)碼授予類(lèi)型的高級(jí)流程:
我將有兩個(gè)應(yīng)用程序-一個(gè)資源服務(wù)器公開(kāi)用戶的一些資源,以及一個(gè)客戶端應(yīng)用程序代表用戶訪問(wèn)這些資源。 如前面的博客文章所述,可以啟動(dòng)授權(quán)服務(wù)器本身。
文章的其余部分可以更輕松地跟隨我的github存儲(chǔ)庫(kù)中的代碼
授權(quán)服務(wù)器
可以使用我之前的博客文章中描述的步驟輕松啟動(dòng)Cloud Foundry UAA服務(wù)器。 一旦完成,可以使用以下uaac命令來(lái)填充運(yùn)行樣本所需的不同憑據(jù)。
這些腳本將為客戶端應(yīng)用程序創(chuàng)建客戶端證書(shū),并添加一個(gè)名為“ user1”的用戶,其范圍為“ resource.read”和“ resource.write”。
# Login as a canned client uaac token client get admin -s adminsecret# Add a client credential with client_id of client1 and client_secret of client1 uaac client add client1 \--name client1 \--scope resource.read,resource.write \-s client1 \--authorized_grant_types authorization_code,refresh_token,client_credentials \--authorities uaa.resource# Another client credential resource1/resource1 uaac client add resource1 \--name resource1 \-s resource1 \--authorized_grant_types client_credentials \--authorities uaa.resource# Add a user called user1/user1 uaac user add user1 -p user1 --emails user1@user1.com# Add two scopes resource.read, resource.write uaac group add resource.read uaac group add resource.write# Assign user1 both resource.read, resource.write scopes.. uaac member add resource.read user1 uaac member add resource.write user1資源服務(wù)器
資源服務(wù)器通過(guò)以下方式公開(kāi)了一些端點(diǎn),這些端點(diǎn)使用Spring MVC表示并使用Spring Security進(jìn)行保護(hù):
@RestController public class GreetingsController {@PreAuthorize("#oauth2.hasScope('resource.read')")@RequestMapping(method = RequestMethod.GET, value = "/secured/read")@ResponseBodypublic String read(Authentication authentication) {return String.format("Read Called: Hello %s", authentication.getCredentials());}@PreAuthorize("#oauth2.hasScope('resource.write')")@RequestMapping(method = RequestMethod.GET, value = "/secured/write")@ResponseBodypublic String write(Authentication authentication) {return String.format("Write Called: Hello %s", authentication.getCredentials());} }公開(kāi)了兩個(gè)端點(diǎn)uri –授權(quán)用于范圍“ resource.read”的“ /安全/讀取”和授權(quán)用于范圍“ resource.write”的“ /安全/寫(xiě)入”
保護(hù)這些端點(diǎn)并將應(yīng)用程序標(biāo)記為資源服務(wù)器的配置如下:
@Configuration @EnableResourceServer @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.resourceId("resource");}@Overridepublic void configure(HttpSecurity http) throws Exception {http.antMatcher("/secured/**").authorizeRequests().anyRequest().authenticated();} }該配置以及描述如何驗(yàn)證令牌的屬性是使資源服務(wù)器運(yùn)行所需的全部。
客戶
使用Spring Security OAuth2的OAuth2的客戶端配置也非常簡(jiǎn)單,@ EnableAuth2SSO批注提取所有必需的配置以為OAuth2流連接Spring安全過(guò)濾器:
@EnableOAuth2Sso @Configuration public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {@Overridepublic void configure(WebSecurity web) throws Exception {super.configure(web);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable();//@formatter:offhttp.authorizeRequests().antMatchers("/secured/**").authenticated().antMatchers("/").permitAll().anyRequest().authenticated();//@formatter:on}}要調(diào)用下游系統(tǒng),客戶端必須將OAuth令牌作為標(biāo)頭傳遞到下游調(diào)用中,方法是通過(guò)掛接一個(gè)稱為OAuth2RestTemplate的專(zhuān)用RestTemplate來(lái)完成,該模板可以從上下文中獲取訪問(wèn)令牌并將其傳遞到下游連接了一個(gè)安全的下游呼叫,如下所示:
public class DownstreamServiceHandler {private final OAuth2RestTemplate oAuth2RestTemplate;private final String resourceUrl;public DownstreamServiceHandler(OAuth2RestTemplate oAuth2RestTemplate, String resourceUrl) {this.oAuth2RestTemplate = oAuth2RestTemplate;this.resourceUrl = resourceUrl;}public String callRead() {return callDownstream(String.format("%s/secured/read", resourceUrl));}public String callWrite() {return callDownstream(String.format("%s/secured/write", resourceUrl));}public String callInvalidScope() {return callDownstream(String.format("%s/secured/invalid", resourceUrl));}private String callDownstream(String uri) {try {ResponseEntity<String> responseEntity = this.oAuth2RestTemplate.getForEntity(uri, String.class);return responseEntity.getBody();} catch(HttpStatusCodeException statusCodeException) {return statusCodeException.getResponseBodyAsString();}} }示范
可以使用此處的說(shuō)明啟動(dòng)客戶端和資源服務(wù)器。 一旦所有系統(tǒng)啟動(dòng),訪問(wèn)客戶端將向用戶顯示一個(gè)頁(yè)面,如下所示:
訪問(wèn)安全頁(yè)面將導(dǎo)致授權(quán)服務(wù)器顯示登錄頁(yè)面:
客戶端正在向用戶請(qǐng)求“ resource.read”和“ resource.write”范圍,提示用戶授權(quán)這些范圍:
假設(shè)用戶已授權(quán)“ resource.read”但未授權(quán)“ resource.write”,則令牌將呈現(xiàn)給用戶:
在這一點(diǎn)上,如果請(qǐng)求的下游資源要求范圍為“ resource.read”,則應(yīng)檢索它:
并且,如果請(qǐng)求的下游資源具有用戶未授權(quán)的范圍,在這種情況下為“ resource.write”:
參考
- 大多數(shù)代碼基于此處提供的Cloud Foundry UAA應(yīng)用程序示例– https://github.com/pivotal-cf/identity-sample-apps
- 帖子中的代碼在這里 :https://github.com/bijukunjummen/oauth-uaa-sample
翻譯自: https://www.javacodegeeks.com/2017/03/using-uaa-oauth2-authorization-server-client-resource.html
總結(jié)
以上是生活随笔為你收集整理的使用UAA OAuth2授权服务器–客户端和资源的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: javaee和javaee_JavaEE
- 下一篇: 使用RESTful Client API