授權碼模式:
1.需要提供appid和app密碼
2.配置回調位址
3.驗證token接口
實作流程:
1.引入必要依賴:
security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
oauth2
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
jwt
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.修改security配置
完成這個部分(攔截+使用者校驗部分)
新增授權類
AuthorizationConfig
繼承
AuthorizationServerConfigurerAdapter
,
重寫他的兩個配置方法,
在類中注入我們配置好的加密類:
@Component
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter{
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
}
}
在
AuthorizationServerSecurityConfigurer
參數的方法中配置允許表單送出
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
}
在
ClientDetailsServiceConfigurer
參數的方法中配置
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
//appid
.withClient("gaga")
//appsecret
.secret(passwordEncoder.encode("gaga_test_security"))
//授權碼
.authorizedGrantTypes("authorization_code")
//作用域
.scopes("all")
//資源id
.resourceIds("employed_resource")
//回調位址
.redirectUris("127.0.0.1:18001/callback");
}
在實際開發中我們會将這些資料儲存于DB,當後端認證通過以後執行這個方法的時候我們動态的查詢資料庫,将資訊寫入,類似權限添加部分;
這就完成了;
認證:
當我們通路
http://127.0.0.1:18001/oauth/authorize?client_id=
employed
&response_type=code
client_id寫上自己的appid,type=code;
- 當我們通路的時候如果沒有登入會提示我們登入;當我們登入成功後就會提示我們是否願意讓上面我們配置的
的用戶端擷取我們的appid
資料資訊
- 當點選同意擷取的時候,頁面就會重定向到我們指定的回調函數,并且後面附帶一個參數,授權碼;
- 這時候我們背景就能通過回調位址擷取到授權碼,根據授權碼生成Token
- 根據授權碼擷取acccessToken;通路:
授權碼http://127.0.0.1:18001/oauth/token?code=
對應我們配置中的每一條配置;&grant_type=authorization_code&redirect_url=http://127.0.0.1:18001/callback&scope=all
- 這時候又會讓我們登入,但是這時候是需要用
進行登入,并appid的賬戶和密碼
;意思就是我們不是使用者
拿到了商家用戶端
以後,用授權碼換取token,這時候需要我們使用者的授權
亮明身份換取商家
;token
- 實際中就是我們拿到
,以使用者授權碼
的身份換取商家
的使用者
;注意需要token
方法,認證方法選擇post
,提供賬号密碼進行請求;就能擷取到tokenbasic
{
"access_token": "9455a88a-f6c7-4916-bf51-4d5c054153c4",
"token_type": "bearer",
"expires_in": 43050,
"scope": "all"
}
- 從
拿到了token我們就可以去調用在我們這個中心注冊了的oauth伺服器
;商家的接口
小結:大緻思路就是當
1.
第三方
軟體請求聯合登入的時候,會拉起
主應用
,
2.
主應用
向伺服器申請一個
特殊的token[
未登入提示登入],
3.然後
token
交給
第三方應用
,
4.
第三方應用
拿着
token
就可以向
主應用的伺服器
請求
使用者資源
;[第三方應用未登入也要提示登入,也就是提供合作時我們分發的
appid
和
密鑰
]
資源服務保護的配置:
在我們需要保護資源的服務中建立一個資源服務配置類
ResurceConifg
繼承
ResourceServerConfigurerAdapter
類;
注入兩個參數,appid以及密鑰;後續需要db查詢
,配置了這個的服務在被請求時必須帶上簽發的正确token才行;
@Configuration//啟用配置
@EnableResourceServer//啟用資源服務
public class ResurceConifg extends ResourceServerConfigurerAdapter {
private String appid = "employed";//這裡後續需要從資料庫中查詢周遊用下面的方法填入記憶體
private String appSecret = "employed_test_security";//這裡後續需要從資料庫中查詢周遊用下面的方法填入記憶體
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Primary
@Bean
public RemoteTokenServices remoteTokenServices() {
//這裡後續需要從資料庫中查詢周遊用下面的方法填入記憶體
final RemoteTokenServices tokenServices = new RemoteTokenServices();
//設定授權伺服器check_token的端點完整位址
tokenServices.setCheckTokenEndpointUrl("http://127.0.0.1:18001/oauth/check_token");
//設定用戶端id與secret,這裡的secret不能使用加密!
tokenServices.setClientId(appid);
tokenServices.setClientSecret(appSecret);
return tokenServices;
}
@Override
public void configure(HttpSecurity http) throws Exception {
//設定建立session政策.設定請求後;
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
//@formatter:off
//設定所有請求都必須授權
http.authorizeRequests()
.anyRequest().authenticated();
//@formatter:on
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
//設定保護的資源,這個資源就是注冊在我們oauth伺服器記憶體中個各個商家的資源id,這個服務中要配置好這個才能保護;
resources.resourceId("employed_resource").stateless(true);
}
}
http://127.0.0.1:18081/oauth/check_token?token=14d20998-864f-4eb7-9ca8-af1c86fbc1da
總結:
- 先向
使用者索取同意操作,使用者同意之後會以使用者的身份頒布一個授權碼;已登入
-
拿着第三方平台
,向授權伺服器申請token;授權碼
- 第三方平台使用
就可以向accessToken
使用者授權伺服器管轄的
請求資料,擷取使用者資訊個人資源伺服器
- 第三方平台就可以根據使用者資訊進行登入或者注冊操作;
- 補充:資源釋出的時候會給自己指定一個資源id,而第三方進行accsesToken申請的時候也會指定一個資源id(數組),是以隻能通路與之比對的對應資源
誤區:
之前一直以為是向授權伺服器拿到token以後就可以用token通路第三方的資源了,正覺得奇怪,豈不是每次token都需要授權伺服器來解密?
你要是頭鐵這麼做也能用 ,
原來資源伺服器并不是代表着第三方平台
,而是代表着
受開放平台管理
的
使用者資源
;
我開始還以為資源伺服器就是第三方,第三方token經過授權伺服器的驗證後就可以請求第三方的接口;昨天測試的時候直接就把這個token放到業務代碼裡去了
感謝這個老哥的圖解,一下就明白了,碰巧查資源id的時候看到的圖
Spring Security OAuth2之resource_id配置與驗證
想法:
由于一開始的不了解,是以也想了一些替代方法,這邊記錄一下,說不定會派上用場,第三方可以直接使用token進行替代使用者登入,隻是登入以後另外頒發一個使用者的專屬token然後就不用授權伺服器的token了。。token失效以後再重新擷取;