SpringSecurity+OAuth2.0?搭建認證中心和資源服務中心流程分析
1. OAuth2.0 簡介
OAuth 2.0(開放授權 2.0)是一個開放標準,用于授權第三方應用程序訪問用戶在資源所有者(用戶)的帳戶上存儲的受保護資源,而無需共享用戶憑據(jù)。OAuth 2.0 主要用于在互聯(lián)網(wǎng)上安全地委托授權,廣泛應用于身份驗證和授權場景。
以下是 OAuth 2.0 的核心概念和流程:
角色:
- 資源所有者(Resource Owner): 擁有受保護資源的用戶。
- 客戶端(Client): 第三方應用程序,希望訪問資源所有者的受保護資源。
- 授權服務器(Authorization Server): 負責驗證資源所有者并頒發(fā)訪問令牌的服務器。
- 資源服務器(Resource Server): 存儲受保護資源的服務器,它可以與授權服務器相同,也可以是不同的服務器。
授權類型:OAuth2.0協(xié)議一共支持 4 種不同的授權模式:
授權碼模式:常見的第三方平臺登錄功能基本都是使用這種模式。
簡化模式:簡化模式是不需要客戶端服務器參與,直接在瀏覽器中向授權服務器申請令牌(token),一般如果網(wǎng)站是純靜態(tài)頁面則可以采用這種方式。
密碼模式:密碼模式是用戶把用戶名密碼直接告訴客戶端,客戶端使用說這些信息向授權服務器申請令牌(token)。這需要用戶對客戶端高度信任,例如客戶端應用和服務提供商就是同一家公司,自己做前后端分離登錄就可以采用這種模式。
客戶端模式:客戶端模式是指客戶端使用自己的名義而不是用戶的名義向服務提供者申請授權,嚴格來說,客戶端模式并不能算作 OAuth 協(xié)議要解決的問題的一種解決方案,但是,對于開發(fā)者而言,在一些前后端分離應用或者為移動端提供的認證授權服務器上使用這種模式還是非常方便的。
2. 代碼搭建
2.1 認證中心(8080端口)
導入依賴
<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的認證管理器,密碼模式需要用到 */ @Autowired private AuthenticationManager authenticationManager; /** * 配置令牌訪問的安全約束 */ @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security //開啟/oauth/token_key驗證端口權限訪問 .tokenKeyAccess("permitAll()") //開啟/oauth/check_token驗證端口認證權限訪問 .checkTokenAccess("permitAll()") //表示支持 client_id 和 client_secret 做登錄認證 .allowFormAuthenticationForClients(); } //配置客戶端 @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //內(nèi)存模式 clients.inMemory() //客戶端id .withClient("test") //客戶端秘鑰 .secret(new BCryptPasswordEncoder().encode("123456")) //資源id,唯一,比如訂單服務作為一個資源,可以設置多個 .resourceIds("order") //授權模式,總共四種,1. authorization_code(授權碼模式)、password(密碼模式)、client_credentials(客戶端模式)、implicit(簡化模式) //refresh_token并不是授權模式, .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token") //允許的授權范圍,客戶端的權限,這里的all只是一種標識,可以自定義,為了后續(xù)的資源服務進行權限控制 .scopes("all") //false 則跳轉到授權頁面 .autoApprove(false) //授權碼模式的回調(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); //令牌服務 services.setTokenStore(tokenStore()); //access_token的過期時間 services.setAccessTokenValiditySeconds(60 * 60 * 2); //refresh_token的過期時間 services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3); return services; } /** * 授權碼模式的service,使用授權碼模式authorization_code必須注入 */ @Bean public AuthorizationCodeServices authorizationCodeServices() { //授權碼存在內(nèi)存中 return new InMemoryAuthorizationCodeServices(); } /** * 配置令牌訪問的端點 */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints //授權碼模式所需要的authorizationCodeServices .authorizationCodeServices(authorizationCodeServices()) //密碼模式所需要的authenticationManager .authenticationManager(authenticationManager) //令牌管理服務,無論哪種模式都需要 .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)存中加載用戶,實際生產(chǎn)中需要從數(shù)據(jù)庫中加載 auth.inMemoryAuthentication() .withUser("admin") .password(new BCryptPasswordEncoder().encode("123456")) .roles("admin");//后面可以跟and連接 } /** * AuthenticationManager對象在OAuth2認證服務中要使用,提前放入IOC容器中 * Oauth的密碼模式需要 */ @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
2.2 資源服務中心(8081端口)
導入依賴和認證中心相同,添加一個配置類ResourceServerConfig
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { /** * 配置令牌校驗服務,客戶端攜帶令牌訪問資源,作為資源端必須檢驗令牌的真?zhèn)? * TODO 使用JWT作為TOKEN則不必遠程調(diào)用check_token校驗 */ @Bean public RemoteTokenServices tokenServices() { //遠程調(diào)用授權服務的check_token進行令牌的校驗 RemoteTokenServices services = new RemoteTokenServices(); // /oauth/check_token 這個url是認證中心校驗的token的端點 services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token"); //客戶端的唯一id services.setClientId("test"); //客戶端的秘鑰 services.setClientSecret("123456"); return services; } /** * 配置資源id和令牌校驗服務 */ @Override public void configure(ResourceServerSecurityConfigurer resources) { //配置唯一資源id resources.resourceId("order") //配置令牌校驗服務 .tokenServices(tokenServices()); } /** * 配置security的安全機制 */ @Override public void configure(HttpSecurity http) throws Exception { //#oauth2.hasScope()校驗客戶端的權限,這個all是在客戶端中的scope http.authorizeRequests() .antMatchers("/**").access("#oauth2.hasScope('all')") .anyRequest().authenticated(); } }
測試接口
@RestController public class TestController { @GetMapping("/test") public String hello() { return "hello world"; } }
3. 測試結果
訪問http://localhost:8080/oauth/authorize?client_id=test&response_type=code&scope=all&redirect_uri=http://www.baidu.com
登錄,賬號admin,密碼123456,然后獲取授權碼
獲取令牌
訪問資源中心
未攜帶令牌測試結果
攜帶令牌測試結果
到此這篇關于SpringSecurity+OAuth2.0 搭建認證中心和資源服務中心的文章就介紹到這了,更多相關SpringSecurity OAuth2.0 認證中心內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!