Spring Cloud Oauth2 初探
關(guān)鍵字
OAuth2
spring cloud
spring security
你需要知道的
一個(gè)原則: 使用前一定先看官方文檔妙同,看不懂再來搜尋第三方資料。
- 你需要熟悉OAuth2.0的相關(guān)規(guī)范,以及各種授權(quán)方式的應(yīng)用場(chǎng)景與流程。
- Spring Security 官方文檔
- Spring OAuth2 官方文檔
為何開始
一個(gè)Spring框架的應(yīng)用,需要一種能夠保護(hù) API 接口的實(shí)現(xiàn)泼各,嘗試過 OAuth1.0
,發(fā)現(xiàn)更多的是有關(guān)OAuth2.0
的討論,且Spring Security 也有隊(duì)OAuth2
的支持查描,于是轉(zhuǎn)而使用OAuth2
。
環(huán)境
Frame | version |
---|---|
Centos | 7 |
Spring Boot | 2.0.0.RELEASE |
Spring Cloud | Finchley.M8 |
Oracle JDK | 1.8 |
IDE | Idea |
依賴
其中核心依賴僅有
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
其中 Spring Security 已經(jīng)包含在 Starter 中柏卤,無(wú)需再次聲明冬三,以保持 pom 簡(jiǎn)潔。
OAuth2 Authorization Server
要使用OAuth2 服務(wù)器缘缚,僅需要使用 @EnableAuthorizationServer
注解勾笆。
此外OAuth2 Server還依賴于Spring Security,還需要加上@EnableWebSecurity
注解桥滨。
當(dāng)然窝爪,這還不夠,根據(jù)Spring Security官方文檔齐媒,你還需要繼承WebSecurityConfigurerAdapter
類以使Security配置生效蒲每。
你可以繼承但不做任何改動(dòng),以使用默認(rèn)配置喻括。
默認(rèn)的WebSecurity安全配置與OAuth2Server安全配置不會(huì)產(chǎn)生沖突邀杏,無(wú)需過濾
/oauth/**
端點(diǎn)。
該注解(@EnableAuthorizationServer)可以加在任何
@Configuration
注解的地方唬血,推薦放在相關(guān)的配置類上望蜡,而不推薦放在入口類**Application
上。
OAuthServerConfig.class
@Configuration
@EnableAuthorizationServer
@EnableWebSecurity
public class Oauth2ServerConfig {
/**
* Spring Security 安全配置
*/
@Configuration
public static class CustomWebSecurityConfiguration extends WebSecurityConfigurerAdapter {}
}
啟動(dòng)程序刁品,可以看到 OAuth2 的相關(guān)接口已經(jīng)實(shí)現(xiàn)了泣特,Spring 的自動(dòng)配置已經(jīng)為我們做了許多工作了,以致于我們可以開箱即用挑随。
值得注意的是状您,自動(dòng)配置類為我們生成了一個(gè)用戶名為:user
的 "user" 和一個(gè) "client" :
2018-03-24 21:20:22.916 INFO 931 --- [ main] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: d457f3b2-a3d7-4ace-bfaf-44ab7bfd8ccc
2018-03-24 21:20:23.181 INFO 931 --- [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/authorize]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.String>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)
2018-03-24 21:20:23.183 INFO 931 --- [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/authorize],methods=[POST],params=[user_oauth_approval]}" onto public org.springframework.web.servlet.View org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.approveOrDeny(java.util.Map<java.lang.String, java.lang.String>,java.util.Map<java.lang.String, ?>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)
2018-03-24 21:20:23.185 INFO 931 --- [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/token],methods=[GET]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
2018-03-24 21:20:23.185 INFO 931 --- [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/token],methods=[POST]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
2018-03-24 21:20:23.186 INFO 931 --- [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/check_token]}" onto public java.util.Map<java.lang.String, ?> org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.checkToken(java.lang.String)
2018-03-24 21:20:23.186 INFO 931 --- [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/confirm_access]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint.getAccessConfirmation(java.util.Map<java.lang.String, java.lang.Object>,javax.servlet.http.HttpServletRequest) throws java.lang.Exception
2018-03-24 21:20:23.186 INFO 931 --- [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/error]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint.handleError(javax.servlet.http.HttpServletRequest)
2018-03-24 21:20:23.536 INFO 931 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']]], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2287395, org.springframework.security.web.context.SecurityContextPersistenceFilter@41b64020, org.springframework.security.web.header.HeaderWriterFilter@15fb4566, org.springframework.security.web.authentication.logout.LogoutFilter@3b009e7b, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@3e33b52e, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@78910096, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@79e7188e, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@535a518c, org.springframework.security.web.session.SessionManagementFilter@29896529, org.springframework.security.web.access.ExceptionTranslationFilter@6a15b73, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@7741d346]
2018-03-24 21:20:23.563 INFO 931 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@ac91282, org.springframework.security.web.context.SecurityContextPersistenceFilter@67332b1e, org.springframework.security.web.header.HeaderWriterFilter@39941489, org.springframework.security.web.csrf.CsrfFilter@536b71b4, org.springframework.security.web.authentication.logout.LogoutFilter@1e5eb20a, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@1e8fb66f, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@60cb1ed6, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@3d8d17a3, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7e34b127, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@679dd234, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@7f79edee, org.springframework.security.web.session.SessionManagementFilter@6f5d0190, org.springframework.security.web.access.ExceptionTranslationFilter@789c3057, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1f9d4b0e]
2018-03-24 21:20:23.726 INFO 931 --- [ main] a.OAuth2AuthorizationServerConfiguration : Initialized OAuth2 Client
security.oauth2.client.client-id = 64b5dabe-a97c-4f60-8492-acd24fc7599d
security.oauth2.client.client-secret = f8934b27-c7d6-4821-bd7e-1f7270e7e7b8
嘗試攜帶上面的信息進(jìn)行GET請(qǐng)求:
http://127.0.0.1:8080/oauth/authorize?client_id=64b5dabe-a97c-4f60-8492-acd24fc7599d&response_type=code&scope=user&redirect_uri=http://www.baidu.com
會(huì)跳轉(zhuǎn)到/login
頁(yè)面進(jìn)行登錄驗(yàn)證,填入 user
和 log 中的密碼 d457f3b2-a3d7-4ace-bfaf-44ab7bfd8ccc
即可驗(yàn)證通過兜挨。
重新跳轉(zhuǎn)回授權(quán)頁(yè)面膏孟,選擇Approve
同意并進(jìn)行授權(quán)后,頁(yè)面跳轉(zhuǎn)至redirect_url
并攜帶code
信息拌汇。
https://www.baidu.com/?code=bPVWmn
取得 code 之后,就可以向服務(wù)器繼續(xù)請(qǐng)求access-token
了柒桑,使用 POST 方法繼續(xù)請(qǐng)求。
需要注意的是你需要添加 Basic Auth 信息在請(qǐng)求頭噪舀,
username
為 "client_id" ,password
為 "client_secret"
不出意外魁淳,你將會(huì)看到以下信息:
{
"access_token":"9d646451-c672-4aa6-a864-2e10ed0f29f1",
"token_type":"bearer",
"refresh_token":"d7c1c3ca-a30e-4889-b993-abf32822117d",
"expires_in":42138,
"scope":"user"
}
至此飘诗,我們已經(jīng)完成了一整個(gè)authorization_code
類型的OAuth2授權(quán)了。
OAuth Resource Server
依賴
同樣的界逛,你只需要一個(gè)依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
//todo: 未完成...