1浪读、概述
Spring Cloud 的安全模塊可以為Spring Boot應(yīng)用提供基于令牌的安全特性流译。具體講就是支持OAuth2協(xié)議來實(shí)現(xiàn)單點(diǎn)登錄(SSO)封字,可以很方便地在資源服務(wù)之間傳遞身份令牌黔州,以及使用嵌入式的ZUUL代理來配置下游服務(wù)的認(rèn)證。
在這篇文章中阔籽,我們將介紹如何在Spring Boot 客戶端應(yīng)用流妻、身份認(rèn)證服務(wù)與提供REST API的資源服務(wù)之間配置完成這些功能。實(shí)現(xiàn)系統(tǒng)的安全訪問控制笆制、身份認(rèn)證和單點(diǎn)登錄绅这。
在這個(gè)例子中,我們使用了2個(gè)客戶端應(yīng)用程序來演示云安全特性中的SSO在辆,只不過這2個(gè)應(yīng)用是一樣的证薇。
2度苔、創(chuàng)建云安全應(yīng)用
首先在所有Spring Boot應(yīng)用中配置SSO,需要增加spring-cloud-starter-oauth2依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
它會(huì)自動(dòng)包含spring-cloud-starter-security依賴浑度。
然后配置一個(gè)應(yīng)用作為身份認(rèn)證服務(wù)寇窑,認(rèn)證服務(wù)部署為http://localhost:7070/authserver。認(rèn)證服務(wù)使用JWT令牌箩张。
由于有多個(gè)客戶端來連接Spring OAuth2 Auth Server甩骏,需要在配置類里為inMemory生成器定義多個(gè)withClients。
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("first").secret("passwordforauthserver")
.redirectUris("http://localhost:8080/").authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("myscope").autoApprove(true).accessTokenValiditySeconds(30).refreshTokenValiditySeconds(1800)
.and()
.withClient("second").secret("passwordforauthserver")
.redirectUris("http://localhost:8081/").authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("myscope").autoApprove(true).accessTokenValiditySeconds(30).refreshTokenValiditySeconds(1800);
}
另外需要配置一個(gè)資源服務(wù)伏钠,代表受保護(hù)的服務(wù)横漏。服務(wù)端口為9000。
提供REST服務(wù)接口供客戶端調(diào)用熟掂。
@RestController
public class PersonInfoController {
@GetMapping("/person")
@PreAuthorize("hasAnyRole('ADMIN', 'USER')")
public @ResponseBody Person personInfo() {
return new Person("peter", "Beijing", "China", 29, "Male");
}
}
同時(shí)提供一個(gè)/usr接口供客戶端來獲得用戶的憑證缎浇。
@RestController
public class ResourceController {
@RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
}
最后是客戶端應(yīng)用,在配置類里增加安全注解:
@Configuration
@EnableOAuth2Sso
public class SiteSecurityConfigurer
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// ...
}
}
任何需要身份驗(yàn)證的請(qǐng)求都將被重定向到授權(quán)服務(wù)器赴肚。為此素跺,我們還必須定義服務(wù)器屬性:
security:
oauth2:
client:
accessTokenUri: http://localhost:7070/authserver/oauth/token
userAuthorizationUri: http://localhost:7070/authserver/oauth/authorize
clientId: first
clientSecret: passwordforauthserver
resource:
userInfoUri: http://localhost:9000/user
3、傳遞令牌
當(dāng)傳遞令牌時(shí)誉券,OAuth2客戶端將其接收到的OAuth2令牌轉(zhuǎn)發(fā)給資源服務(wù)指厌。由于我們已經(jīng)聲明了@EnableOauth2Sso注解,Spring Boot 會(huì)在請(qǐng)求上下文中添加一個(gè)OAuth2ClientContext對(duì)象踊跟,因此我們可以在客戶端應(yīng)用程序中創(chuàng)建自己的OAuth2RestTemplate踩验。
@Bean
public OAuth2RestOperations restOperations(
OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
return new OAuth2RestTemplate(resource, context);
}
一旦我們配置了這個(gè)Bean,上下文就會(huì)將訪問令牌轉(zhuǎn)發(fā)給所請(qǐng)求的服務(wù)商玫,并且如果令牌到期了也將會(huì)刷新令牌箕憾。
4、使用RestTemplate傳遞OAuth令牌
之前我們?cè)诳蛻舳藨?yīng)用程序中定義了一個(gè)OAuth2RestTemplate 類型的restOperations bean拳昌。因此可以使用OAuth2RestTemplate中的getForObject() 方法來發(fā)送帶有令牌的請(qǐng)求到受保護(hù)的資源服務(wù)袭异。
@Autowired
private RestOperations restOperations;
@GetMapping("/personInfo")
public ModelAndView person() {
ModelAndView mav = new ModelAndView("personinfo");
String personResourceUrl = "http://localhost:9000/person";
mav.addObject("person",
restOperations.getForObject(personResourceUrl, String.class));
return mav;
}
5、配置Zuul傳遞令牌
如果我們想把一個(gè)令牌轉(zhuǎn)發(fā)給代理服務(wù)炬藤,我們可以使用Spring Cloud Zuul嵌入式反向代理御铃。
在客戶端應(yīng)用中引入Zuul依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
然后在配置類里添加@EnableZuulProxy 注解
@Configuration
@EnableOAuth2Sso
@EnableZuulProxy
public class SiteSecurityConfigurer
extends WebSecurityConfigurerAdapter {
//...
}
同時(shí)在application.yml 文件里添加Zuul的配置項(xiàng)
zuul:
routes:
resource:
path: /api/**
url: http://localhost:9000
user:
path: /user/**
url: http://localhost:9000/user
這樣任何訪問客戶端應(yīng)用/api端點(diǎn)的請(qǐng)求被重定向到資源服務(wù)的URL。這些請(qǐng)求都會(huì)帶著OAuth令牌沈矿。
6上真、運(yùn)行效果
直接訪問受保護(hù)的資源服務(wù),顯示未認(rèn)證
訪問客戶端http://localhost:8080/personInfo羹膳,重定向到身份認(rèn)證頁面
輸入用戶名谷羞、密碼(user/user),顯示資源服務(wù)數(shù)據(jù)
通過Zuul代理訪問資源服務(wù)
7、總結(jié)
在這篇文章里湃缎,我們討論了如何使用Spring Cloud Security的OAuth2和Zuul來配置安全的認(rèn)證服務(wù)和資源服務(wù)犀填,以及使用Oauth2RestTemplate和嵌入的Zuul代理在服務(wù)之間傳遞OAuth2令牌。示例代碼下載地址