SpringSecurity+OAuth2.0?搭建認(rèn)證中心和資源服務(wù)中心流程分析
1. OAuth2.0 簡(jiǎn)介
OAuth 2.0(開(kāi)放授權(quán) 2.0)是一個(gè)開(kāi)放標(biāo)準(zhǔn),用于授權(quán)第三方應(yīng)用程序訪問(wèn)用戶在資源所有者(用戶)的帳戶上存儲(chǔ)的受保護(hù)資源,而無(wú)需共享用戶憑據(jù)。OAuth 2.0 主要用于在互聯(lián)網(wǎng)上安全地委托授權(quán),廣泛應(yīng)用于身份驗(yàn)證和授權(quán)場(chǎng)景。
以下是 OAuth 2.0 的核心概念和流程:
角色:
- 資源所有者(Resource Owner): 擁有受保護(hù)資源的用戶。
- 客戶端(Client): 第三方應(yīng)用程序,希望訪問(wèn)資源所有者的受保護(hù)資源。
- 授權(quán)服務(wù)器(Authorization Server): 負(fù)責(zé)驗(yàn)證資源所有者并頒發(fā)訪問(wèn)令牌的服務(wù)器。
- 資源服務(wù)器(Resource Server): 存儲(chǔ)受保護(hù)資源的服務(wù)器,它可以與授權(quán)服務(wù)器相同,也可以是不同的服務(wù)器。
授權(quán)類型:OAuth2.0協(xié)議一共支持 4 種不同的授權(quán)模式:
授權(quán)碼模式:常見(jiàn)的第三方平臺(tái)登錄功能基本都是使用這種模式。
簡(jiǎn)化模式:簡(jiǎn)化模式是不需要客戶端服務(wù)器參與,直接在瀏覽器中向授權(quán)服務(wù)器申請(qǐng)令牌(token),一般如果網(wǎng)站是純靜態(tài)頁(yè)面則可以采用這種方式。
密碼模式:密碼模式是用戶把用戶名密碼直接告訴客戶端,客戶端使用說(shuō)這些信息向授權(quán)服務(wù)器申請(qǐng)令牌(token)。這需要用戶對(duì)客戶端高度信任,例如客戶端應(yīng)用和服務(wù)提供商就是同一家公司,自己做前后端分離登錄就可以采用這種模式。
客戶端模式:客戶端模式是指客戶端使用自己的名義而不是用戶的名義向服務(wù)提供者申請(qǐng)授權(quán),嚴(yán)格來(lái)說(shuō),客戶端模式并不能算作 OAuth 協(xié)議要解決的問(wèn)題的一種解決方案,但是,對(duì)于開(kāi)發(fā)者而言,在一些前后端分離應(yīng)用或者為移動(dò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>
只需要添加兩個(gè)配置類即可
MyAuthorizationConfig類
@Configuration @EnableAuthorizationServer public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter { /** * 客戶端存儲(chǔ)策略,這里使用內(nèi)存方式,后續(xù)可以存儲(chǔ)在數(shù)據(jù)庫(kù) */ @Autowired private ClientDetailsService clientDetailsService; /** * Security的認(rèn)證管理器,密碼模式需要用到 */ @Autowired private AuthenticationManager authenticationManager; /** * 配置令牌訪問(wèn)的安全約束 */ @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security //開(kāi)啟/oauth/token_key驗(yàn)證端口權(quán)限訪問(wèn) .tokenKeyAccess("permitAll()") //開(kāi)啟/oauth/check_token驗(yàn)證端口認(rèn)證權(quán)限訪問(wè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ù)作為一個(gè)資源,可以設(shè)置多個(gè) .resourceIds("order") //授權(quán)模式,總共四種,1. authorization_code(授權(quán)碼模式)、password(密碼模式)、client_credentials(客戶端模式)、implicit(簡(jiǎn)化模式) //refresh_token并不是授權(quán)模式, .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token") //允許的授權(quán)范圍,客戶端的權(quán)限,這里的all只是一種標(biāo)識(shí),可以自定義,為了后續(xù)的資源服務(wù)進(jìn)行權(quán)限控制 .scopes("all") //false 則跳轉(zhuǎn)到授權(quán)頁(yè)面 .autoApprove(false) //授權(quán)碼模式的回調(diào)地址 .redirectUris("http://www.baidu.com"); //可以and繼續(xù)添加客戶端 } /** * 令牌存儲(chǔ)策略 */ @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的過(guò)期時(shí)間 services.setAccessTokenValiditySeconds(60 * 60 * 2); //refresh_token的過(guò)期時(shí)間 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(); } /** * 配置令牌訪問(wèn)的端點(diǎn) */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints //授權(quán)碼模式所需要的authorizationCodeServices .authorizationCodeServices(authorizationCodeServices()) //密碼模式所需要的authenticationManager .authenticationManager(authenticationManager) //令牌管理服務(wù),無(wú)論哪種模式都需要 .tokenServices(tokenServices()) //只允許POST提交訪問(wèn)令牌,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ù)庫(kù)中加載 auth.inMemoryAuthentication() .withUser("admin") .password(new BCryptPasswordEncoder().encode("123456")) .roles("admin");//后面可以跟and連接 } /** * AuthenticationManager對(duì)象在OAuth2認(rèn)證服務(wù)中要使用,提前放入IOC容器中 * Oauth的密碼模式需要 */ @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
2.2 資源服務(wù)中心(8081端口)
導(dǎo)入依賴和認(rèn)證中心相同,添加一個(gè)配置類ResourceServerConfig
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { /** * 配置令牌校驗(yàn)服務(wù),客戶端攜帶令牌訪問(wèn)資源,作為資源端必須檢驗(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 這個(gè)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)限,這個(gè)all是在客戶端中的scope http.authorizeRequests() .antMatchers("/**").access("#oauth2.hasScope('all')") .anyRequest().authenticated(); } }
測(cè)試接口
@RestController public class TestController { @GetMapping("/test") public String hello() { return "hello world"; } }
3. 測(cè)試結(jié)果
訪問(wèn)http://localhost:8080/oauth/authorize?client_id=test&response_type=code&scope=all&redirect_uri=http://www.baidu.com
登錄,賬號(hào)admin,密碼123456,然后獲取授權(quán)碼
獲取令牌
訪問(wèn)資源中心
未攜帶令牌測(cè)試結(jié)果
攜帶令牌測(cè)試結(jié)果
到此這篇關(guān)于SpringSecurity+OAuth2.0 搭建認(rèn)證中心和資源服務(wù)中心的文章就介紹到這了,更多相關(guān)SpringSecurity OAuth2.0 認(rèn)證中心內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java版仿QQ驗(yàn)證碼風(fēng)格圖片驗(yàn)證碼
這篇文章主要為大家分享了java圖片驗(yàn)證碼實(shí)例代碼,感興趣的小伙伴們可以參考一下2016-04-04java教學(xué)筆記之對(duì)象的創(chuàng)建與銷毀
面向?qū)ο蟮木幊陶Z(yǔ)言使程序能夠直觀的反應(yīng)客觀世界的本來(lái)面目,并且使軟件開(kāi)發(fā)人員能夠運(yùn)用人類認(rèn)識(shí)事物所采用的一般思維方法進(jìn)行軟件開(kāi)發(fā),是當(dāng)今計(jì)算機(jī)領(lǐng)域中軟件開(kāi)發(fā)和應(yīng)用的主流技術(shù)。2016-01-01java中 Set與Map排序輸出到Writer詳解及實(shí)例
這篇文章主要介紹了 java中 Set與Map排序輸出到Writer詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03SpringBoot 過(guò)濾器與攔截器實(shí)例演示
本文通過(guò)示例代碼給大家講解SpringBoot 過(guò)濾器與攔截器的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-11-11