4. spring-security-oauth2 server

上篇文章介紹了OAuth2的一般過(guò)程和原理,并且使用GitHub作為認(rèn)證服務(wù)器實(shí)戰(zhàn)Client端的代碼煮落,本文在之前代碼的基礎(chǔ)上改造成可以鑒權(quán)的oauth2 server

初步講解套路


OAuth2 認(rèn)證

還是以此圖為例启搂,寫好server端一定要留意上圖server中的三個(gè)模塊:

  • Resource Owner:即指需要授權(quán)訪問(wèn)的資源计维,比如用戶昵稱扫责,頭像
  • Authorization Server:鑒權(quán)服務(wù),核心鑒權(quán)邏輯
  • Resource Server:資源服務(wù)

配合代碼中的三個(gè)注解:

  • EnableAuthorizationServer:配置授權(quán)服務(wù)
  • EnableResourceServer:配置授權(quán)資源路徑
  • EnableOAuth2Client:配置Client信息

實(shí)戰(zhàn)代碼


修改WebSecurityConfig:


@Configuration
@EnableOAuth2Client
@EnableAuthorizationServer
@Order(6)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Autowired
    OAuth2ClientContext oauth2ClientContext;

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        // Configure spring security's authenticationManager with custom
        // user details service
        auth.userDetailsService(this.userService);
    }

    @Override
    @Bean // share AuthenticationManager for web and oauth
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/user/**").authenticated()
                .anyRequest().permitAll()
                .and().exceptionHandling()
                .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
                .and()
                .formLogin().loginPage("/login").loginProcessingUrl("/login.do").defaultSuccessUrl("/user/info")
                .failureUrl("/login?err=1")
                .permitAll()
                .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .permitAll()

                .and().addFilterBefore(githubFilter(), BasicAuthenticationFilter.class)
        ;

    }

    private Filter githubFilter() {
        OAuth2ClientAuthenticationProcessingFilter githubFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/github");
        OAuth2RestTemplate githubTemplate = new OAuth2RestTemplate(githubClient().getClient(), oauth2ClientContext);
        githubFilter.setRestTemplate(githubTemplate);
        githubFilter.setTokenServices(new UserInfoTokenServices(githubClient().getResource().getUserInfoUri(), githubClient().getClient().getClientId()));
        return githubFilter;
    }

    @Bean
    @ConfigurationProperties("github")
    public ClientResources githubClient() {
        return new ClientResources();
    }

    @Bean
    public FilterRegistrationBean oauth2ClientFilterRegistration(
            OAuth2ClientContextFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(filter);
        registration.setOrder(-100);
        return registration;
    }

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/**").authorizeRequests().anyRequest().authenticated();
        }
    }
}
...
// client resource
public class ClientResources {

    @NestedConfigurationProperty
    private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

    @NestedConfigurationProperty
    private ResourceServerProperties resource = new ResourceServerProperties();

    public AuthorizationCodeResourceDetails getClient() {
        return client;
    }

    public ResourceServerProperties getResource() {
        return resource;
    }
}

主要就加了@EnableAuthorizationServer注解告訴spring啟動(dòng)Server模式碰镜,github登錄跟上篇文章的代碼一樣兢卵,就是封裝了一下,因?yàn)橐郧按a的注解ResourceServerProperties會(huì)和spring 的EnableAuthorizationServer沖突绪颖,加上了EnableResourceServer秽荤,配置/api/**底下的資源是需要權(quán)限的,重寫AuthenticationManager這個(gè)方法很重要柠横,目的是將web登錄和oauth登錄的manager共享窃款,不然只能有一方生效,這個(gè)想了解的可以讀一讀源碼牍氛,一時(shí)解釋不太清楚晨继。

新加了UserRestController:

@RestController
@RequestMapping("/api/users")
public class UserRestController {

    @Autowired
    IUserService userService;

    @RequestMapping("")
    public List<User> all() {

        return userService.findAll();
    }
}

普通業(yè)務(wù)。
最后在application-dev.yml配置client信息搬俊,:

security:
  oauth2:
    client:
      client-id: client
      client-secret: secret
      scope: read,write
      auto-approve-scopes: '.*'
      grant-type: password
  basic:
    enabled: false

可以看出這里的字段就對(duì)應(yīng)上文做client端的字段信息紊扬。

運(yùn)行效果


網(wǎng)頁(yè)瀏覽器端沒(méi)有任何變化,可以使用admin/admin登錄唉擂,也可以使用github登錄餐屎。這應(yīng)該和一般見(jiàn)到的網(wǎng)站一樣了,測(cè)試client端可以使用curl

  1. curl -u client:secret http://localhost:8090/oauth/token -d "username=admin&password=admin&scope=read&grant_type=password":先使用password模式獲取token玩祟,可以看到參數(shù)跟上篇文章講解里的是一樣的腹缩,獲取到的json格式如下
{"access_token":"7e7b7ced-3747-43a2-8134-c7e6b87c6451","token_type":"bearer","refresh_token":"b254c018-e5c4-42e3-bd30-269657b6262b","expires_in":43199,"scope":"read"}
  1. 接下來(lái)就可以用token請(qǐng)求/api資源了:curl http://localhost:8090/api/users -H "Authorization: bearer 7e7b7ced-3747-43a2-8134-c7e6b87c6451",獲取的User列表json:
[{"id":1,"username":"admin","password":"admin","role":"ROLE_ADMIN","enabled":true,"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true,"authorities":[{"authority":"ROLE_ADMIN"}]}]
  1. 如果直接請(qǐng)求curl http://localhost:8090/api/users則返回鑒權(quán)失敗:{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
    一般向單頁(yè)應(yīng)用或手機(jī)APP大致是這樣的流程了藏鹊。

最后胜臊,現(xiàn)在這個(gè)Demo差不多完備了,自身的用戶可以登錄伙判,第三方github等也可以登錄,手機(jī)APP等移動(dòng)端也可以登錄黑忱,完整代碼照例打了tag宴抚,github地址 v1.8

發(fā)現(xiàn)有些新手不理解curl命令是如何轉(zhuǎn)化為rest請(qǐng)求的甫煞,在這里回來(lái)補(bǔ)充一下菇曲,上文中的curl -u client:secret http://localhost:8090/oauth/token -d "username=admin&password=admin&scope=read&grant_type=password"命令簡(jiǎn)單來(lái)說(shuō)可以換成curl -H "Authorization: Basic Y2xpZW50OnNlY3JldA==" http://localhost:8090/oauth/token -d "username=admin&password=admin&scope=read&grant_type=password"-H命令是添加請(qǐng)求頭信息抚吠,keyAuthorization常潮,value中的Basic是固定的代表基本認(rèn)證Basic后面有一個(gè)空格),后面的字符串是認(rèn)證信息比如client+secret字符串相加做base64加密之后的加密串楷力。

下篇文章將記錄如何自定義上述功能喊式,spring-security-oauth2好多功能都是一個(gè)注解都封裝好了,但是有時(shí)還是需要在自己的業(yè)務(wù)里做定制萧朝,國(guó)內(nèi)需求環(huán)境你們都懂的岔留。.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市检柬,隨后出現(xiàn)的幾起案子献联,更是在濱河造成了極大的恐慌,老刑警劉巖何址,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件里逆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡用爪,警方通過(guò)查閱死者的電腦和手機(jī)原押,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)项钮,“玉大人班眯,你說(shuō)我怎么就攤上這事∷肝祝” “怎么了署隘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)亚隙。 經(jīng)常有香客問(wèn)我磁餐,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任诊霹,我火速辦了婚禮羞延,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘脾还。我一直安慰自己伴箩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布鄙漏。 她就那樣靜靜地躺著嗤谚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怔蚌。 梳的紋絲不亂的頭發(fā)上巩步,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音桦踊,去河邊找鬼椅野。 笑死,一個(gè)胖子當(dāng)著我的面吹牛籍胯,可吹牛的內(nèi)容都是我干的竟闪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼芒炼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瘫怜!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起本刽,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鲸湃,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后子寓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體暗挑,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年斜友,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了炸裆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鲜屏,死狀恐怖烹看,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洛史,我是刑警寧澤惯殊,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站也殖,受9級(jí)特大地震影響土思,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一己儒、第九天 我趴在偏房一處隱蔽的房頂上張望崎岂。 院中可真熱鬧,春花似錦闪湾、人聲如沸冲甘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)损合。三九已至,卻和暖如春娘纷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跋炕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工赖晶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辐烂。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓遏插,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親纠修。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胳嘲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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