Spring Security OAuth2認證授權(quán)示例詳解
本文介紹了如何使用Spring Security OAuth2構(gòu)建一個授權(quán)服務(wù)器來驗證用戶身份以提供access_token,并使用這個access_token來從資源服務(wù)器請求數(shù)據(jù)。
1.概述
OAuth2是一種授權(quán)方法,用于通過HTTP協(xié)議提供對受保護資源的訪問。首先,OAuth2使第三方應(yīng)用程序能夠獲得對HTTP服務(wù)的有限訪問權(quán)限,然后通過資源所有者和HTTP服務(wù)之間的批準交互來讓第三方應(yīng)用程序代表資源所有者獲取訪問權(quán)限。
1.1 角色
OAuth定義了四個角色
- 資源所有者 - 應(yīng)用程序的用戶。
- 客戶端 - 需要訪問資源服務(wù)器上的用戶數(shù)據(jù)的應(yīng)用程序。
- 資源服務(wù)器 - 存儲用戶數(shù)據(jù)和http服務(wù),可以將用戶數(shù)據(jù)返回給經(jīng)過身份驗證的客戶端。
- 授權(quán)服務(wù)器 - 負責(zé)驗證用戶的身份并提供授權(quán)令牌。資源服務(wù)器接受此令牌并驗證您的身份。
OAuth2的交互過程:
1.2 訪問令牌與刷新令牌
訪問令牌代表一個向客戶授權(quán)的字符串。令牌包含了由資源所有者授予的權(quán)限范圍和訪問持續(xù)時間,并由資源服務(wù)器和授權(quán)服務(wù)器強制執(zhí)行。
授權(quán)服務(wù)器向客戶端發(fā)出刷新令牌,用于在當前訪問令牌失效或過期時獲取新的訪問令牌,或獲取具有相同或更窄范圍的其他訪問令牌,新的訪問令牌可能具有比資源所有者授權(quán)的更短的生命周期和更少的權(quán)限。根據(jù)授權(quán)服務(wù)器的判斷,發(fā)布刷新令牌是可選的。
訪問令牌的責(zé)任是在數(shù)據(jù)到期之前訪問它。
刷新令牌的責(zé)任是在現(xiàn)有訪問令牌過期時請求新的訪問令牌。
2. OAuth2 - 授權(quán)服務(wù)器
要使用spring Security OAuth2模塊創(chuàng)建授權(quán)服務(wù)器,我們需要使用注解@EnableAuthorizationServer并擴展AuthorizationServerConfigurerAdapter類。
@Configuration @EnableAuthorizationServer public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter { @Autowired private BCryptPasswordEncoder passwordEncoder; @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()") .allowFormAuthenticationForClients(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient("clientapp") .secret(passwordEncoder.encode("654321")) .authorizedGrantTypes("password", "authorization_code", "refresh_token") .authorities("READ_ONLY_CLIENT").scopes("read_user_info") .resourceIds("oauth2-resource") .redirectUris("http://localhost:8081/login") .accessTokenValiditySeconds(5000) .refreshTokenValiditySeconds(50000); } }
Spring Security OAuth2會公開了兩個端點,用于檢查令牌(/oauth/check_token和/oauth/token_key),這些端點默認受保護denyAll()。tokenKeyAccess()和checkTokenAccess()方法會打開這些端點以供使用。
ClientDetailsServiceConfigurer用于定義客戶端詳細的服務(wù)信息,它可以在內(nèi)存中或在數(shù)據(jù)庫中定義。
在本例中我們使用了內(nèi)存實現(xiàn)。它具有以下重要屬性:
- clientId - (必需)客戶端ID。
- secret - (可信客戶端所需)客戶端密鑰(可選)。
- scope - 客戶受限的范圍。如果范圍未定義或為空(默認值),則客戶端不受范圍限制。
- authorizedGrantTypes - 授權(quán)客戶端使用的授權(quán)類型。默認值為空。
- authorities - 授予客戶的權(quán)限(常規(guī)Spring Security權(quán)限)。
- redirectUris - 將用戶代理重定向到客戶端的重定向端點。它必須是絕對URL。
3. OAuth2 - 資源服務(wù)器
要創(chuàng)建資源服務(wù)器組件,請使用@EnableResourceServer注解并擴展ResourceServerConfigurerAdapter類。
@Configuration @EnableResourceServer public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/api/**").authenticated(); } }
以上配置啟用/api下所有端點的保護,但可以自由訪問其他端點。
資源服務(wù)器還提供了一種對用戶自己進行身份驗證的機制。在大多數(shù)情況下,它通常是基于表單的登錄。
@Configuration @Order(1) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/**") .requestMatchers() .antMatchers("/oauth/authorize**", "/login**", "/error**") .and() .authorizeRequests().anyRequest().authenticated() .and() .formLogin().permitAll(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("peterwanghao") .password(passwordEncoder().encode("123456")).roles("USER"); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
4. OAuth2保護的REST資源
本例中只創(chuàng)建了一個RESTful API,它返回登錄用戶的姓名和電子郵件。
@Controller public class RestResource { @RequestMapping("/api/users/me") public ResponseEntity<UserInfo> profile() { User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String email = user.getUsername() + "@126.com"; UserInfo profile = new UserInfo(); profile.setName(user.getUsername()); profile.setEmail(email); return ResponseEntity.ok(profile); } }
public class UserInfo { private String name; private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User [name=" + name + ", email=" + email + "]"; } }
5.演示
我們有一個API http://localhost:8080/api/users/me ,我們想通過第三方應(yīng)用程序來訪問API需要OAuth2令牌。
5.1 從用戶獲取授權(quán)許可代碼
如上面的序列圖所示,第一步是從URL獲取資源所有者的授權(quán):
http://localhost:8080/oauth/authorize?client_id=clientapp&response_type=code&scope=read_user_info
通過瀏覽器訪問上面的URL地址,它將展現(xiàn)一個登錄頁面。提供用戶名和密碼。對于此示例,請使用“peterwanghao”和“123456”。
登錄后,您將被重定向到授予訪問頁面,您可以在其中選擇授予對第三方應(yīng)用程序的訪問權(quán)限。
它會重定向到URL,如:http://localhost:8081/login?code=TUXuk9 。這里'TUXuk9'是第三方應(yīng)用程序的授權(quán)代碼。
5.2 從授權(quán)服務(wù)器獲取訪問令牌
現(xiàn)在,應(yīng)用程序?qū)⑹褂檬跈?quán)碼來獲取訪問令牌。在這里,我們需要提出以下請求。使用此處第一步中獲得的代碼。
curl -X POST --user clientapp:654321 http://localhost:8080/oauth/token -H "content-type: application/x-www-form-urlencoded" -d "code=TUXuk9&grant_type=authorization_code&redirect_uri=http://localhost:8081/login&scope=read_user_info"
訪問令牌響應(yīng)
{ "access_token": "168aad01-05dc-4446-9fba-fd7dbe8adb9e", "token_type": "bearer", "refresh_token": "34065175-1e92-4bb0-918c-a5a6ece1dc5f", "expires_in": 4999, "scope": "read_user_info" }
5.3 從資源服務(wù)器訪問用戶數(shù)據(jù)
一旦我們有了訪問令牌,我們就可以轉(zhuǎn)到資源服務(wù)器來獲取受保護的用戶數(shù)據(jù)。
curl -X GET http://localhost:8080/api/users/me -H "authorization: Bearer 168aad01-05dc-4446-9fba-fd7dbe8adb9e"
獲得資源響應(yīng)
{ "name":"peterwanghao", "email":"peterwanghao@126.com" }
6.總結(jié)
本文講解了OAuth2授權(quán)框架的實現(xiàn)機制,通過一個例子說明了第三方應(yīng)用程序如何通過授權(quán)服務(wù)器的授權(quán)去資源服務(wù)器上獲取受保護的數(shù)據(jù)。本例的完整代碼在GitHub 上。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Spring gateway配置Spring Security實現(xiàn)統(tǒng)一權(quán)限驗證與授權(quán)示例源碼
- Springboot使用Security實現(xiàn)OAuth2授權(quán)驗證完整過程
- springboot+jwt+springSecurity微信小程序授權(quán)登錄問題
- Spring Security OAuth2 授權(quán)碼模式的實現(xiàn)
- Spring Security 控制授權(quán)的方法
- 詳解使用Spring Security OAuth 實現(xiàn)OAuth 2.0 授權(quán)
- Spring security中的授權(quán)
相關(guān)文章
thymeleaf中前后端數(shù)據(jù)交互方法匯總
這篇文章主要介紹了thymeleaf中前后端數(shù)據(jù)交互小結(jié),本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2022-07-07詳解領(lǐng)域驅(qū)動設(shè)計之事件驅(qū)動與CQRS
這篇文章分析了如何應(yīng)用事件來分離軟件核心復(fù)雜度。探究CQRS為什么廣泛應(yīng)用于DDD項目中,以及如何落地實現(xiàn)CQRS框架。當然我們也要警惕一些失敗的教訓(xùn),利弊分析以后再去抉擇正確的應(yīng)對之道2021-06-06