Spring Cloud 安全:集成OAuth2實(shí)現(xiàn)身份認(rèn)證和單點(diǎn)登錄

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)證


11.png

訪問客戶端http://localhost:8080/personInfo羹膳,重定向到身份認(rèn)證頁面

22.png

輸入用戶名谷羞、密碼(user/user),顯示資源服務(wù)數(shù)據(jù)


33.png

通過Zuul代理訪問資源服務(wù)


44.png

7、總結(jié)

在這篇文章里湃缎,我們討論了如何使用Spring Cloud Security的OAuth2和Zuul來配置安全的認(rèn)證服務(wù)和資源服務(wù)犀填,以及使用Oauth2RestTemplate和嵌入的Zuul代理在服務(wù)之間傳遞OAuth2令牌。示例代碼下載地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嗓违,一起剝皮案震驚了整個(gè)濱河市九巡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蹂季,老刑警劉巖冕广,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異偿洁,居然都是意外死亡撒汉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門涕滋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來睬辐,“玉大人,你說我怎么就攤上這事宾肺∷荻” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵锨用,是天一觀的道長丰刊。 經(jīng)常有香客問我,道長增拥,這世上最難降的妖魔是什么啄巧? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮掌栅,結(jié)果婚禮上秩仆,老公的妹妹穿的比我還像新娘。我一直安慰自己渣玲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布弟晚。 她就那樣靜靜地躺著忘衍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卿城。 梳的紋絲不亂的頭發(fā)上枚钓,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音瑟押,去河邊找鬼搀捷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嫩舟。 我是一名探鬼主播氢烘,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼家厌!你這毒婦竟也來了播玖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤饭于,失蹤者是張志新(化名)和其女友劉穎蜀踏,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掰吕,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡果覆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了殖熟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片局待。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吗讶,靈堂內(nèi)的尸體忽然破棺而出燎猛,到底是詐尸還是另有隱情,我是刑警寧澤照皆,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布重绷,位于F島的核電站,受9級(jí)特大地震影響膜毁,放射性物質(zhì)發(fā)生泄漏昭卓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一瘟滨、第九天 我趴在偏房一處隱蔽的房頂上張望候醒。 院中可真熱鬧,春花似錦杂瘸、人聲如沸倒淫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敌土。三九已至,卻和暖如春运翼,著一層夾襖步出監(jiān)牢的瞬間返干,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來泰國打工血淌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留矩欠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像癌淮,于是被迫代替她去往敵國和親躺坟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容