使用Spring Boot構建獨立的OAuth服務器(一)

最近公司系統重構,須要提供API接口給其餘部門調用,因爲架構緣由,這些API有可能會被外部訪問,基於安全性的考慮,決定使用OAuth來保護這些API,以避免被隨意調用。html

因爲系統衆多,不可能在每一個系統中都配置OAuth認證受權功能,所以須要構建一個獨立的OAuth服務器,專門負責認證受權,這裏採用的框架是Spring Boot。java

整個認證受權流程中有三個角色:web

  • 客戶端(Client)
  • API接口(Resource)
  • OAuth服務器(Authorization Server)

受權模式有四種:spring

  • 受權碼模式(Authorization Code)
  • 簡化模式(Implicit)
  • 密碼模式(Resource Owner Password Credentials)
  • 客戶端模式(Client Credentials)

具體定義可看理解 OAuth 2.0json

由於訪問OAuth服務器的都是公司內部系統,而且不可能使用同一個登陸頁面,因此只有密碼模式適用,所以後面配置的時候也只配置密碼模式。安全

具體流程以下圖服務器

  1. 客戶端向OAuth服務器申請Access Token
  2. 認證受權成功後OAuth服務器會返回Access Token給客戶端
  3. 客戶端帶着Access Token調用API接口
  4. API接口把Access Token交給OAuth服務器檢查
  5. 若是Access Token有效,OAuth服務器會返回用戶相關信息(用戶名,角色等)給API接口
  6. API接口根據檢查結果來決定返回給客戶端的內容

下面開始實現一個簡單版的OAuth服務器架構

  1. 在pom.xml中配置依賴包和插件
    <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.6.RELEASE</version>
        </parent>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth</groupId>
                <artifactId>spring-security-oauth2</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>

     

  2. 編寫主類Application
    @SpringBootApplication
    @EnableAuthorizationServer
    @EnableWebSecurity
    public class Application {
    
    	public static void main(String[] args) {
    		SpringApplication.run(Application.class, args);
    	}
    
    }

     

  3. 編寫OAuth配置類OauthConfig,這裏將Token存儲在內存中
    @Configuration
    @ImportResource("classpath:/client.xml")
    public class OauthConfig extends AuthorizationServerConfigurerAdapter {
    
    	@Autowired
    	private AuthenticationManager authenticationManager;
    
    	@Override
    	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    		endpoints.tokenServices(tokenServices(endpoints)).authenticationManager(authenticationManager);
    	}
    
    	private DefaultTokenServices tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
    		DefaultTokenServices services = new DefaultTokenServices();
    		services.setTokenStore(tokenStore());
    		services.setSupportRefreshToken(true);
    		services.setReuseRefreshToken(false);
    		services.setClientDetailsService(endpoints.getClientDetailsService());
    		return services;
    	}
    
    	private TokenStore tokenStore() {
    		return new InMemoryTokenStore();
    	}
    
    }

     

  4. 在client.xml中配置client信息,這裏使用xml文件來配置是由於以爲管理方便
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
    	xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<oauth2:client-details-service id="clientDetailsService">
    		<oauth2:client client-id="client1" secret="secret1" 
    			authorized-grant-types="password,refresh_token" access-token-validity="1800" 
    			refresh-token-validity="604800" scope="all" />
    	</oauth2:client-details-service>
    
    </beans>

     

  5. 編寫用戶查詢類CustomUserDetailsService,定義一個固定用戶,用戶名爲user,密碼爲pwd,角色爲ROLE_USER
    @Component
    public class CustomUserDetailsService implements UserDetailsService {
    
    	@Override
    	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    		return new User("user", "pwd", AuthorityUtils.createAuthorityList("ROLE_USER"));
    	}
    
    }

     

測試方法框架

  1. 使用Maven運行Goal:clean spring-boot:run
  2. 使用接口調用工具,如Postman,配置HTTP Basic認證,用戶名和密碼分別對應client.xml中的client-id和secret,使用POST方法和參數grant_type:password,username:user,password:pwd來調用http://localhost:8080/oauth/token,若調用成功便會返回以下格式的JSON字符串
    {
        "access_token": "352d9a1c-86aa-4011-9732-4beca4d9f848",
        "token_type": "bearer",
        "refresh_token": "c2295cbf-e33c-4fac-a4c8-eaea25c4c72b",
        "expires_in": 1799,
        "scope": "all"
    }

     

至此便構建了一個簡單版的OAuth服務器maven

後面在 使用Spring Boot構建獨立的OAuth服務器(二) 中會進行更多的配置。

相關文章
相關標籤/搜索