您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關SpringCloud中怎么使用OAuth2.0實現鑒權,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
Spring Security是一個功能強大、高度可定制的身份驗證和訪問控制框架。它用于保護基于Spring的應用程序。Spring Security是一個專注于向Java應用程序提供身份驗證和授權的框架。 與所有Spring項目一樣,Spring安全的真正威力在于它可以很容易地擴展以滿足定制需求。
OAuth 2.0是用于授權的行業標準協議。OAuth3.0注重客戶端開發人員的簡單性,同時為Web應用程序、桌面應用程序、移動電話和客廳設備提供特定的授權流。 更多請參考 OAuth3.0
OAuth3.0模式
模式 | 應用場景 | 描述 |
---|---|---|
授權碼(Auth Code) | 成功后跳轉其他頁面,如第三方微信登錄等 | |
簡化模式(implicit) | 不通過第三方應用程序的服務器,直接在瀏覽器中向認證服務器申請令牌 | |
密碼模式(password credentials) | web頁面用戶名密碼登錄 | |
客戶端模式(client credentials) | 主要針對openapi,使用apikey和secretkey方式 |
JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案。更多請參考 JWT入門教程
核心pom依賴如下:
<!-- 注意是starter,自動配置 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- 不是starter,手動配置 --> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth3</artifactId> <version>2.3.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 將token存儲在redis中 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
創建一個rest接口用于后面測試資源
@Slf4j @RestController public class TestSecurityController { @GetMapping("/product/{id}") public String getProduct(@PathVariable String id) { //for debug Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); return "product id : " + id; } @GetMapping("/order/{id}") public String getOrder(@PathVariable String id) { //for debug Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); return "order id : " + id; } }
很多文章寫的特別復雜,其實主要的內容也就分為下面幾步
AuthorizationServerConfigurerAdapter
需要自定義授權服務器,繼承AuthorizationServerConfigurerAdapter
,詳細代碼如下
@Configuration @EnableAuthorizationServer public class AuthServerConfiguration extends AuthorizationServerConfigurerAdapter { private static final String DEMO_RESOURCE_ID = "order"; @Autowired AuthenticationManager authenticationManager; @Autowired RedisConnectionFactory redisConnectionFactory; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //配置兩個客戶端,一個用于password認證一個用于client認證 String secret = new BCryptPasswordEncoder().encode("123456");////對密碼進行加密 clients.inMemory().withClient("client_1") .resourceIds(DEMO_RESOURCE_ID) .authorizedGrantTypes("client_credentials", "refresh_token") .scopes("select") .authorities("client") .secret(secret) .and().withClient("client_2") .resourceIds(DEMO_RESOURCE_ID) .authorizedGrantTypes("password", "refresh_token") .scopes("select") .authorities("client") .secret(secret); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(new RedisTokenStore(redisConnectionFactory)) .authenticationManager(authenticationManager); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { //允許表單認證 oauthServer.allowFormAuthenticationForClients(); } }
ResourceServerConfigurerAdapter
同上,需要實現自己的資源服務器,繼承ResourceServerConfigurerAdapter
,詳細代碼如下
@Configuration @EnableResourceServer public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { private static final String DEMO_RESOURCE_ID = "order"; @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(DEMO_RESOURCE_ID).stateless(true); } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http // Since we want the protected resources to be accessible in the UI as well we need // session creation to be allowed (it's disabled by default in 2.0.6) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() .requestMatchers().anyRequest() .and() .anonymous() .and() .authorizeRequests() // .antMatchers("/product/**").access("#oauth3.hasScope('select') and hasRole('ROLE_USER')") .antMatchers("/order/**").authenticated();//配置order訪問控制,必須認證過后才可以訪問 // @formatter:on } }
@Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean @Override protected UserDetailsService userDetailsService(){ InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); String pwd = new BCryptPasswordEncoder().encode("123456");//對密碼進行加密 manager.createUser(User.withUsername("user_1").password(pwd).authorities("USER").build()); manager.createUser(User.withUsername("user_2").password(pwd).authorities("USER").build()); return manager; } @Override protected void configure(HttpSecurity http) throws Exception { http .requestMatchers().anyRequest() .and() .authorizeRequests() .antMatchers("/oauth/*").permitAll(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { AuthenticationManager manager = super.authenticationManagerBean(); return manager; } @Bean PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }
我們設計的是product
服務可以匿名訪問,而order
服務需要簽名才可以訪問,驗證如下:
password模式 利用postman進行post訪問http://localhost:8080/oauth/token?username=user_1&password=123456&grant_type=password&scope=select&client_id=client_2&client_secret=123456
獲取如下結果
{ "access_token": "c2340190-48f3-4291-bb17-1e4d51bcb284", "token_type": "bearer", "refresh_token": "03ee113c-a942-452a-9918-7ffe24472a7f", "expires_in": 40399, "scope": "select" }
client模式 同樣利用postman的POST方式訪問http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456
結果如下
{ "access_token": "05a4e614-f34b-4c83-9ec1-89ea55c0afd2", "token_type": "bearer", "expires_in": 40396, "scope": "select" }
product服務:訪問http://localhost:8080/product/1
得到如下數據
product id : 1
order服務:訪問http://localhost:8080/order/1
,返回數據如下
<oauth> <error_description> Full authentication is required to access this resource </error_description> <error>unauthorized</error> </oauth>
驗證結果,說明order服務需要簽名才可以訪問,接下來,我們輸入簽名訪問order服務。 我們分別利用上面password模式獲取的token,訪問 http://localhost:8080/order/1?access_token=c2340190-48f3-4291-bb17-1e4d51bcb284 得到數據 order id : 1
通用利用client模式獲取的token,訪問 http://localhost:8080/order/1?access_token=05a4e614-f34b-4c83-9ec1-89ea55c0afd2 同樣可以得到 order id : 1
以上就是SpringCloud中怎么使用OAuth2.0實現鑒權,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。