SpringBoot2 整合OAuth2組件,模擬第三方授權訪問

<dependency>

? ? <groupId>org.springframework.boot</groupId>

? ? <artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

? ? <groupId>org.springframework.security.oauth</groupId>

? ? <artifactId>spring-security-oauth2</artifactId>

? ? <version>2.1.3.RELEASE</version>

</dependency>

<dependency>

? ? <groupId>org.springframework.boot</groupId>

? ? <artifactId>spring-boot-starter-security</artifactId>

</dependency>

這里有兩個核心組件依賴:OAuth2組件和Security組件。

模塊劃分

auth-server:授權服務

resource-server:資源服務器

third-server:第三個服務

2、配置描述

【授權服務】

OAuth2配置

這里的配置管理的是第三方的授權流程和發放給第三方的身份證明ClientID和密碼,實際的場景就是第三方借助郵箱賬號登錄,首先就是向郵箱管理方提供材料,獲取訪問郵箱服務的身份證明,然后才能對接開放服務,這種模式在第三方對接業務中很常見。

/**

* 模擬第三方授權配置

*/

@EnableAuthorizationServer

@Configuration

public class AuthConfig extends AuthorizationServerConfigurerAdapter {

? ? @Resource

? ? ClientDetailsService clientDetailsService;

? ? /**

? ? * 資源服務器校驗Token

? ? */

? ? @Override

? ? public void configure(AuthorizationServerSecurityConfigurer security) {

? ? ? ? security.checkTokenAccess("permitAll()").allowFormAuthenticationForClients();

? ? }

? ? /**

? ? * 第三方客戶端請求配置,和資源服務訪問的配置,不設置默認都可以訪問,提供默認回調地址

? ? */

? ? @Override

? ? public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

? ? ? ? clients.inMemory()

? ? ? ? ? ? ? ? .withClient("third01")

? ? ? ? ? ? ? ? .secret(new BCryptPasswordEncoder().encode("third01"))

? ? ? ? ? ? ? ? .resourceIds("resource-01")

? ? ? ? ? ? ? ? .authorizedGrantTypes("authorization_code","refresh_token")

? ? ? ? ? ? ? ? .scopes("all")

? ? ? ? ? ? ? ? .redirectUris("http://localhost:8082/notify.html");

? ? }

? ? /**

? ? * 配置訪問端點

? ? */

? ? @Override

? ? public void configure(AuthorizationServerEndpointsConfigurer endpoints) {

? ? ? ? endpoints.authorizationCodeServices(authorizationCodeServices()).tokenServices(tokenServices());

? ? }

? ? /**

? ? * 內存管理

? ? */

? ? @Bean

? ? AuthorizationCodeServices authorizationCodeServices() {

? ? ? ? return new InMemoryAuthorizationCodeServices();

? ? }

? ? /**

? ? * Token管理規則

? ? */

? ? @Bean

? ? AuthorizationServerTokenServices tokenServices() {

? ? ? ? DefaultTokenServices services = new DefaultTokenServices();

? ? ? ? services.setClientDetailsService(clientDetailsService);

? ? ? ? services.setSupportRefreshToken(true);

? ? ? ? services.setTokenStore(tokenStore());

? ? ? ? services.setAccessTokenValiditySeconds(3600);

? ? ? ? services.setRefreshTokenValiditySeconds(3600*7);

? ? ? ? return services;

? ? }

? ? @Bean

? ? TokenStore tokenStore() {

? ? ? ? return new InMemoryTokenStore();

? ? }

}

通常需要數據庫存儲第三方信息,可以到第OAuth2開源項目中,獲取表結構放到本地數據庫中,然后這里換成數據源加載模式即可,簡單的流程管理都在源碼里寫了SQL語句,數據源引入即可。

Security配置

/**

* 模擬本地用戶配置

*/

@Configuration

public class SecurityConfig extends WebSecurityConfigurerAdapter {

? ? /**

? ? * 密碼加密方式

? ? */

? ? @Bean

? ? public PasswordEncoder passwordEncoder(){

? ? ? ? return new BCryptPasswordEncoder();

? ? }

? ? /**

? ? * 內存中虛擬用戶和角色

? ? */

? ? @Override

? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception {

? ? ? ? auth.inMemoryAuthentication()

? ? ? ? ? ? ? ? .withUser("user")

? ? ? ? ? ? ? ? .password(new BCryptPasswordEncoder().encode("123456"))

? ? ? ? ? ? ? ? .roles("user");

? ? }

? ? /**

? ? * 表單登錄

? ? */

? ? @Override

? ? protected void configure(HttpSecurity http) throws Exception {

? ? ? ? http.csrf().disable().formLogin();

? ? }

}

基于這里的配置管理郵箱用戶的認證流程,例如使用郵箱賬號密碼登錄驗證,判斷授權是否成立,這里管理的是服務本地的郵箱賬號,基于數據源存儲數據在下面案例中都有。

案例一:JWT組件管理身份驗證機制

案例二:Shiro組件實現用戶權限管理

案例三:Security用戶安全認證流程

關于Spring框架中安全認證的相關的幾個組件,在使用OAuth2之前可以先了解一下。

【資源服務】

主要功能有三塊,配置第三方攜帶的Token身份令牌校驗機制,即訪問授權服務校驗接口,這里是OAuth2自定義好的接口;配置resourceId資源服務的編號,用來控制第三個服務能訪問的資源服務范圍,屬于大的權限點控制;模擬校驗用戶的Role角色,較精細的控制權限。

/**

* 資源服務管理配置

*/

@Configuration

@EnableResourceServer

public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

? ? /**

? ? * Token令牌校驗

? ? */

? ? @Bean

? ? RemoteTokenServices tokenServices() {

? ? ? ? RemoteTokenServices services = new RemoteTokenServices();

? ? ? ? services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");

? ? ? ? services.setClientId("third01");

? ? ? ? services.setClientSecret("third01");

? ? ? ? return services;

? ? }

? ? /**

? ? * 服務資源ID配置

? ? */

? ? @Override

? ? public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

? ? ? ? resources.resourceId("resource-01").tokenServices(tokenServices());

? ? }

? ? /**

? ? * 模擬用戶權限規則

? ? */

? ? @Override

? ? public void configure(HttpSecurity http) throws Exception {

? ? ? ? http.authorizeRequests()

? ? ? ? ? ? ? ? .antMatchers("/user/**").hasRole("user")

? ? ? ? ? ? ? ? .anyRequest().authenticated();

? ? }

}

【第三方服務】

主要提供兩個流程的模擬:請求授權服務獲取身份令牌;攜帶身份令牌請求資源服務獲取數據。這里則是授權碼回調接口的處理方式。

@Controller

public class NotifyController {

? ? private static final Logger LOG = LoggerFactory.getLogger(NotifyController.class);

? ? @Resource

? ? private RestTemplate restTemplate;

? ? @GetMapping("/notify.html")

? ? public String notify(String code, Model model) {

? ? ? ? if (code != null) {

? ? ? ? ? ? MultiValueMap<String, String> map = new LinkedMultiValueMap<>();

? ? ? ? ? ? map.add("code", code);

? ? ? ? ? ? map.add("client_id", "third01");

? ? ? ? ? ? map.add("client_secret", "third01");

? ? ? ? ? ? map.add("redirect_uri", "http://localhost:8082/notify.html");

? ? ? ? ? ? map.add("grant_type", "authorization_code");

? ? ? ? ? ? Map<String,String> resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);

? ? ? ? ? ? String accessToken = resp.get("access_token");

? ? ? ? ? ? LOG.info("身份令牌:{}",accessToken);

? ? ? ? ? ? HttpHeaders headers = new HttpHeaders();

? ? ? ? ? ? headers.add("Authorization", "Bearer " + accessToken);

? ? ? ? ? ? HttpEntity<Object> httpEntity = new HttpEntity<>(headers);

? ? ? ? ? ? ResponseEntity<String> entity = restTemplate.exchange("http://localhost:8081/user/resource", HttpMethod.GET, httpEntity, String.class);

? ? ? ? ? ? model.addAttribute("notifyMsg", entity.getBody());

? ? ? ? }

? ? ? ? return "notify";

? ? }

}

三、測試流程

通過上述測試流程,對比常見的第三方登錄機制,理解OAuth2的授權碼模式。

四、源代碼地址

GitHub·地址

https://github.com/cicadasmile/middle-ware-parent

GitEE·地址

https://gitee.com/cicadasmile/middle-ware-parent

龍華大道1號 http://www.kinghill.cn/Dynamics/2106.html

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內容