使用Springboot搭建OAuth2.0 Server的方法示例
OAuth是一個關(guān)于授權(quán)(authorization)的開放網(wǎng)絡(luò)標(biāo)準(zhǔn),在全世界得到廣泛應(yīng)用,目前的版本是2.0版。
本文對OAuth 2.0的設(shè)計思路和運行流程,做一個簡明通俗的解釋,主要參考材料為RFC 6749。
OAuth 簡介
OAuth 是由 Blaine Cook、Chris Messina、Larry Halff 及 David Recordon 共同發(fā)起的,目的在于為 API 訪問授權(quán)提供一個安全、開放的標(biāo)準(zhǔn)。
基于 OAuth 認(rèn)證授權(quán)具有以下特點:
- 安全。OAuth 與別的授權(quán)方式不同之處在于:OAuth 的授權(quán)不會使消費方(Consumer)觸及到用戶的帳號信息(如用戶名與密碼),也是是說,消費方無需使用用戶的用戶名與密碼就可以申請獲得該用戶資源的授權(quán)。
- 開放。任何消費方都可以使用 OAuth 認(rèn)證服務(wù),任何服務(wù)提供方 (Service Provider) 都可以實現(xiàn)自身的 OAuth 認(rèn)證服務(wù)。
- 簡單。不管是消費方還是服務(wù)提供方,都很容易于理解與使用。
OAuth 的解決方案如下圖所示。
圖 1. OAuth Solution
如 圖 1 所示 OAuth 解決方案中用戶、消費方及其服務(wù)提供方之間的三角關(guān)系:當(dāng)用戶需要 Consumer 為其提供某種服務(wù)時,該服務(wù)涉及到需要從服務(wù)提供方那里獲取該用戶的保護(hù)資源。OAuth 保證:只有在用戶顯式授權(quán)的情況下(步驟 4),消費方才可以獲取該用戶的資源,并用來服務(wù)于該用戶。
從宏觀層次來看,OAuth 按以下方式工作:
- 消費方與不同的服務(wù)提供方建立了關(guān)系。
- 消費方共享一個密碼短語或者是公鑰給服務(wù)提供方,服務(wù)提供方使用該公鑰來確認(rèn)消費方的身份。
- 消費方根據(jù)服務(wù)提供方將用戶重定向到登錄頁面。
- 該用戶登錄后告訴服務(wù)提供方該消費方訪問他的保護(hù)資源是沒問題的。 前提
閱讀本文之前,你需要了解:
- Spring Boot
- Spring MVC
- Spring Security
- Google 瀏覽器插件Postman
pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.iigrowing.study.oauth2</groupId> <artifactId>demo01</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>my.oauth01</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <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> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
本項目需要添加的依賴非常簡單,一共只有兩個,一個是Spring Web,另一個是Spring OAuth2。
接下來是本文的核心,一共三個配置類。
SecurityConfig
package cn.iigrowing.study.oauth2.demo01; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user").password("123456").authorities("ROLE_USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic() .and().csrf().disable() .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .formLogin() .and() .logout().permitAll(); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
此處主要做了兩件事情:
配置系統(tǒng)用戶,這里使用內(nèi)存存儲,添加了用戶名為 user
,角色為 USER
的用戶
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user").password("123456").authorities("ROLE_USER"); }
配置了默認(rèn)表單登陸以及禁用了 csrf
功能,并開啟了 httpBasic
認(rèn)證
@Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic() .and().csrf().disable() .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .formLogin() .and() .logout().permitAll(); }
AuthorizationServerConfig
package cn.iigrowing.study.oauth2.demo01; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("client").secret("123456").scopes("read") .authorizedGrantTypes("authorization_code") .redirectUris("https://www.getpostman.com/oauth2/callback"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); } }
這個類是OAuth2認(rèn)證的核心配置類,在這個類中,配置了OAuth Client的信息,這里有幾個地方需要注意:
@EnableAuthorizationServer
這個注解告訴 Spring 這個應(yīng)用是 OAuth2 的授權(quán)服務(wù)器- 必須配置
authorizedGrantTypes
,它代表了OAuth Client允許認(rèn)證的類型,其值主要有:
- authorization_code
- password
- client_credentials
- implicit refresh_token
這個配置項接受的類型是個數(shù)組,允許配置多個;關(guān)于這幾種類型的區(qū)別,請查看這里不再贅述
redirectUris
關(guān)于這個配置項,是在 OAuth2協(xié)議中,認(rèn)證成功后的回調(diào)地址,因為稍后我們會使用 Postman
作為測試工具,故此處值固定為 https://www.getpostman.com/oauth2/callback
,此值同樣可以配置多個 ResourceServerConfig
package cn.iigrowing.study.oauth2.demo01; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(“users-info”); } @Override public void configure(HttpSecurity http) throws Exception { http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .requestMatchers() .antMatchers(“/users/**”) .and().authorizeRequests() .antMatchers(“/users/**”) .authenticated(); } }
這個類表明了此應(yīng)用是OAuth2 的資源服務(wù)器,此處主要指定了受資源服務(wù)器保護(hù)的資源鏈接,我們將提供以下的資源:
@RestController @RequestMapping("users") public class UserController { @GetMapping("me") public Principal me(Principal principal) { return principal; } }
注:
資源服務(wù)器可以和授權(quán)服務(wù)器是同一個,也可以分開部署
最后,我們還需添加 application.yml
, 配置資源服務(wù)器的filter的順序
server: port: 8043 context-path: /uaa logging: level: org.springframework.security: DEBUG spring: application: name: oauth-server security: oauth2: resource: serviceId: ${PREFIX:}resource # refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes#oauth-2-resource-filter filter-order: 3
此處的 filter-order
非常重要,因為自Spring Boot 1.5.* 之后,resource server 的 filter 的順序默認(rèn)在 basic authentication filter chain
之后,所以如果不配置此項,將會導(dǎo)致使用 access_token
訪問 resource server 的時候返回 401
狀態(tài)碼。
好了,所有的開發(fā)工作已經(jīng)完成,無需任何其他配置,現(xiàn)在我們啟動服務(wù)器,并通過 Postman
訪問 http://localhost:8043/uaa/users/me
因為現(xiàn)在還沒通過認(rèn)證,所以服務(wù)器將返回 401
的狀態(tài)碼,并返回以上的錯誤信息。
現(xiàn)在我們使用 Postman
來獲取 access_token
,首先選擇 Authorization
Tab, 然后選擇 Type
為 OAuth2.0
,最后點擊 Get New Access Token
按鈕:
此時將彈出以下界面:
我們填入對應(yīng)的信息:
- Token Name: access_token
- Auth URL: http://localhost:8043/uaa/oauth/authorize
- Access Token URL: http://localhost:8043/uaa/oauth/token
- Client ID: client
- Client Secret: 123456
- Grant Type: Authorization Code
此處配置的client相關(guān)信息對應(yīng)了我們在 AuthorizationServerConfig
里面的配置,之前配置的回調(diào)地址也來自于此處的 Callback URL
。
接下來點擊 Request Token
按鈕,在彈出的登陸界面中輸入我們之前在 SecurityConfig
中配置的用戶信息,選擇 Approval
并點擊 Authorize
按鈕,即可獲取 access_token
:
到這里我們就成功的獲取了 token,此時再次調(diào)用 users/me
Api,如無意外,將會得到以下的結(jié)果:
這個項目實現(xiàn)了以下的功能:
- 使用 JWT Token進(jìn)行認(rèn)證
- 多Resource Sever
- 使用數(shù)據(jù)庫存儲用戶以及OAuth Client信息
- 提供相關(guān)的Rest API進(jìn)行用戶及 Client的管理
- 結(jié)合了Spring Cloud
源代碼:my.oauth01
小結(jié)
OAuth 協(xié)議作為一種開放的,基于用戶登錄的授權(quán)認(rèn)證方式,目前互聯(lián)網(wǎng)很多 Open API 都對 OAuth 提供了支持,這包括 Google, Yahoo,Twitter 等。本文以 Google 為例子,介紹了 Java 桌面程序如何開發(fā) OAuth 認(rèn)證應(yīng)用。在開發(fā)桌面應(yīng)用訪問 Web 資源這樣一類程序時,一般通行的步驟是:使用 OAuth 做認(rèn)證,然后使用獲得的 OAuth Access Token,通過 REST API 訪問用戶在服務(wù)提供方的資源。
事實上,目前 OAuth 正通過許多實現(xiàn)(包括針對 Java、C#、Objective-C、Perl、PHP 及 Ruby 語言的實現(xiàn))獲得巨大的動力。大部分實現(xiàn)都由 OAuth 項目維護(hù)并放在 Google 代碼庫 (http://oauth.googlecode.com/svn/) 上。開發(fā)者可以利用這些 OAuth 類庫編寫自己需要的 OAuth 應(yīng)用。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- springboot oauth2實現(xiàn)單點登錄實例
- Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器操作
- springboot集成springsecurity 使用OAUTH2做權(quán)限管理的教程
- 基于SpringBoot整合oauth2實現(xiàn)token認(rèn)證
- springboot2.x實現(xiàn)oauth2授權(quán)碼登陸的方法
- 詳解Springboot Oauth2 Server搭建Oauth2認(rèn)證服務(wù)
- springboot+Oauth2實現(xiàn)自定義AuthenticationManager和認(rèn)證path
- SpringBoot3.X配置OAuth的代碼實踐
相關(guān)文章
spring cloud 使用Zuul 實現(xiàn)API網(wǎng)關(guān)服務(wù)問題
這篇文章主要介紹了spring cloud 使用Zuul 實現(xiàn)API網(wǎng)關(guān)服務(wù)問題,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-05-05Java多種方式實現(xiàn)生產(chǎn)者消費者模式
這篇文章主要介紹了Java多種方式實現(xiàn)生產(chǎn)者消費者模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07SpringBoot后端接收數(shù)組對象的實現(xiàn)
這篇文章主要介紹了SpringBoot后端接收數(shù)組對象的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11SpringBoot2.0集成WebSocket實現(xiàn)后臺向前端推送信息
這篇文章主要介紹了SpringBoot2.0集成WebSocket實現(xiàn)后臺向前端推送信息,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01Spring中的FactoryBean與BeanFactory詳細(xì)解析
這篇文章主要介紹了Spring中的FactoryBean與BeanFactory詳細(xì)解析,在Spring框架中,FactoryBean和BeanFactory是兩個關(guān)鍵的接口,用于創(chuàng)建和管理對象實例,它們在Spring的IoC(Inversion of Control,控制反轉(zhuǎn))容器中發(fā)揮著重要的作用,需要的朋友可以參考下2023-11-11深入了解Spring Boot2.3.0及以上版本的Liveness和Readiness功能
這篇文章主要介紹了Spring Boot2.3.0及以上版本的Liveness和Readiness功能示例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10java開發(fā)gui教程之jframe監(jiān)聽窗體大小變化事件和jframe創(chuàng)建窗體
這篇文章主要介紹了java開發(fā)gui教程中jframe監(jiān)聽窗體大小變化事件和jframe創(chuàng)建窗體的示例,需要的朋友可以參考下2014-03-03