SpringSecurity+OAuth2.0?搭建認(rèn)證中心和資源服務(wù)中心流程分析
1. OAuth2.0 簡介
OAuth 2.0(開放授權(quán) 2.0)是一個開放標(biāo)準(zhǔn),用于授權(quán)第三方應(yīng)用程序訪問用戶在資源所有者(用戶)的帳戶上存儲的受保護(hù)資源,而無需共享用戶憑據(jù)。OAuth 2.0 主要用于在互聯(lián)網(wǎng)上安全地委托授權(quán),廣泛應(yīng)用于身份驗(yàn)證和授權(quán)場景。
以下是 OAuth 2.0 的核心概念和流程:
角色:
- 資源所有者(Resource Owner): 擁有受保護(hù)資源的用戶。
- 客戶端(Client): 第三方應(yīng)用程序,希望訪問資源所有者的受保護(hù)資源。
- 授權(quán)服務(wù)器(Authorization Server): 負(fù)責(zé)驗(yàn)證資源所有者并頒發(fā)訪問令牌的服務(wù)器。
- 資源服務(wù)器(Resource Server): 存儲受保護(hù)資源的服務(wù)器,它可以與授權(quán)服務(wù)器相同,也可以是不同的服務(wù)器。
授權(quán)類型:OAuth2.0協(xié)議一共支持 4 種不同的授權(quán)模式:
授權(quán)碼模式:常見的第三方平臺登錄功能基本都是使用這種模式。

簡化模式:簡化模式是不需要客戶端服務(wù)器參與,直接在瀏覽器中向授權(quán)服務(wù)器申請令牌(token),一般如果網(wǎng)站是純靜態(tài)頁面則可以采用這種方式。

密碼模式:密碼模式是用戶把用戶名密碼直接告訴客戶端,客戶端使用說這些信息向授權(quán)服務(wù)器申請令牌(token)。這需要用戶對客戶端高度信任,例如客戶端應(yīng)用和服務(wù)提供商就是同一家公司,自己做前后端分離登錄就可以采用這種模式。

客戶端模式:客戶端模式是指客戶端使用自己的名義而不是用戶的名義向服務(wù)提供者申請授權(quán),嚴(yán)格來說,客戶端模式并不能算作 OAuth 協(xié)議要解決的問題的一種解決方案,但是,對于開發(fā)者而言,在一些前后端分離應(yīng)用或者為移動端提供的認(rèn)證授權(quán)服務(wù)器上使用這種模式還是非常方便的。

2. 代碼搭建
2.1 認(rèn)證中心(8080端口)
導(dǎo)入依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>只需要添加兩個配置類即可
MyAuthorizationConfig類
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
/**
* 客戶端存儲策略,這里使用內(nèi)存方式,后續(xù)可以存儲在數(shù)據(jù)庫
*/
@Autowired
private ClientDetailsService clientDetailsService;
/**
* Security的認(rèn)證管理器,密碼模式需要用到
*/
@Autowired
private AuthenticationManager authenticationManager;
/**
* 配置令牌訪問的安全約束
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
//開啟/oauth/token_key驗(yàn)證端口權(quán)限訪問
.tokenKeyAccess("permitAll()")
//開啟/oauth/check_token驗(yàn)證端口認(rèn)證權(quán)限訪問
.checkTokenAccess("permitAll()")
//表示支持 client_id 和 client_secret 做登錄認(rèn)證
.allowFormAuthenticationForClients();
}
//配置客戶端
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//內(nèi)存模式
clients.inMemory()
//客戶端id
.withClient("test")
//客戶端秘鑰
.secret(new BCryptPasswordEncoder().encode("123456"))
//資源id,唯一,比如訂單服務(wù)作為一個資源,可以設(shè)置多個
.resourceIds("order")
//授權(quán)模式,總共四種,1. authorization_code(授權(quán)碼模式)、password(密碼模式)、client_credentials(客戶端模式)、implicit(簡化模式)
//refresh_token并不是授權(quán)模式,
.authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")
//允許的授權(quán)范圍,客戶端的權(quán)限,這里的all只是一種標(biāo)識,可以自定義,為了后續(xù)的資源服務(wù)進(jìn)行權(quán)限控制
.scopes("all")
//false 則跳轉(zhuǎn)到授權(quán)頁面
.autoApprove(false)
//授權(quán)碼模式的回調(diào)地址
.redirectUris("http://www.baidu.com"); //可以and繼續(xù)添加客戶端
}
/**
* 令牌存儲策略
*/
@Bean
public TokenStore tokenStore(){
return new InMemoryTokenStore();
}
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices services = new DefaultTokenServices();
//客戶端端配置策略
services.setClientDetailsService(clientDetailsService);
//支持令牌的刷新
services.setSupportRefreshToken(true);
//令牌服務(wù)
services.setTokenStore(tokenStore());
//access_token的過期時間
services.setAccessTokenValiditySeconds(60 * 60 * 2);
//refresh_token的過期時間
services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);
return services;
}
/**
* 授權(quán)碼模式的service,使用授權(quán)碼模式authorization_code必須注入
*/
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
//授權(quán)碼存在內(nèi)存中
return new InMemoryAuthorizationCodeServices();
}
/**
* 配置令牌訪問的端點(diǎn)
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//授權(quán)碼模式所需要的authorizationCodeServices
.authorizationCodeServices(authorizationCodeServices())
//密碼模式所需要的authenticationManager
.authenticationManager(authenticationManager)
//令牌管理服務(wù),無論哪種模式都需要
.tokenServices(tokenServices())
//只允許POST提交訪問令牌,uri:/oauth/token
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
}SecurityConfig類
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 加密算法
*/
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//todo 允許表單登錄
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.permitAll()
.and()
.csrf()
.disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//從內(nèi)存中加載用戶,實(shí)際生產(chǎn)中需要從數(shù)據(jù)庫中加載
auth.inMemoryAuthentication()
.withUser("admin")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles("admin");//后面可以跟and連接
}
/**
* AuthenticationManager對象在OAuth2認(rèn)證服務(wù)中要使用,提前放入IOC容器中
* Oauth的密碼模式需要
*/
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}2.2 資源服務(wù)中心(8081端口)
導(dǎo)入依賴和認(rèn)證中心相同,添加一個配置類ResourceServerConfig
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
/**
* 配置令牌校驗(yàn)服務(wù),客戶端攜帶令牌訪問資源,作為資源端必須檢驗(yàn)令牌的真?zhèn)?
* TODO 使用JWT作為TOKEN則不必遠(yuǎn)程調(diào)用check_token校驗(yàn)
*/
@Bean
public RemoteTokenServices tokenServices() {
//遠(yuǎn)程調(diào)用授權(quán)服務(wù)的check_token進(jìn)行令牌的校驗(yàn)
RemoteTokenServices services = new RemoteTokenServices();
// /oauth/check_token 這個url是認(rèn)證中心校驗(yàn)的token的端點(diǎn)
services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
//客戶端的唯一id
services.setClientId("test");
//客戶端的秘鑰
services.setClientSecret("123456");
return services;
}
/**
* 配置資源id和令牌校驗(yàn)服務(wù)
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
//配置唯一資源id
resources.resourceId("order")
//配置令牌校驗(yàn)服務(wù)
.tokenServices(tokenServices());
}
/**
* 配置security的安全機(jī)制
*/
@Override
public void configure(HttpSecurity http) throws Exception {
//#oauth2.hasScope()校驗(yàn)客戶端的權(quán)限,這個all是在客戶端中的scope
http.authorizeRequests()
.antMatchers("/**").access("#oauth2.hasScope('all')")
.anyRequest().authenticated();
}
}測試接口
@RestController
public class TestController {
@GetMapping("/test")
public String hello() {
return "hello world";
}
}3. 測試結(jié)果
訪問http://localhost:8080/oauth/authorize?client_id=test&response_type=code&scope=all&redirect_uri=http://www.baidu.com
登錄,賬號admin,密碼123456,然后獲取授權(quán)碼


獲取令牌

訪問資源中心
未攜帶令牌測試結(jié)果

攜帶令牌測試結(jié)果

到此這篇關(guān)于SpringSecurity+OAuth2.0 搭建認(rèn)證中心和資源服務(wù)中心的文章就介紹到這了,更多相關(guān)SpringSecurity OAuth2.0 認(rèn)證中心內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java版仿QQ驗(yàn)證碼風(fēng)格圖片驗(yàn)證碼
這篇文章主要為大家分享了java圖片驗(yàn)證碼實(shí)例代碼,感興趣的小伙伴們可以參考一下2016-04-04
java教學(xué)筆記之對象的創(chuàng)建與銷毀
面向?qū)ο蟮木幊陶Z言使程序能夠直觀的反應(yīng)客觀世界的本來面目,并且使軟件開發(fā)人員能夠運(yùn)用人類認(rèn)識事物所采用的一般思維方法進(jìn)行軟件開發(fā),是當(dāng)今計算機(jī)領(lǐng)域中軟件開發(fā)和應(yīng)用的主流技術(shù)。2016-01-01
java中 Set與Map排序輸出到Writer詳解及實(shí)例
這篇文章主要介紹了 java中 Set與Map排序輸出到Writer詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03

