Spring Cloud Security OAuth2.0入門: AuthorizationServer搭建(一)

restlife發表於2019-06-06

最近在學習微服務相關的知識及各種框架的使用,在搭建的過程中,遇到了不少問題,但是都沒有記錄下來,導致過一段時間後,就沒有什麼印象了.. 所以決定在掘金寫文章。 一是為了記錄自己在寫程式碼過程中的知識點以及解決的問題,方便查閱; 二是為了能與其它朋友一起討論,可以吸收不同思想及不同方案,擴充套件思路。

標題之所以為Spring Cloud Security,是因為想要寫Spring Cloud相關的一系列技術。而Spring Cloud依賴Springbootsecurity還是Spring Security模組的東西,本質上沒有太大的區別。

在寫的過程中,遇到自己不熟悉或沒有把握的概念及知識,會謹慎的求證。也會盡量保證釋出的任何程式碼都是可執行的。 但是由於自己技術能力有限,難免會有錯誤,包括但不限於拼寫錯誤程式碼錯誤有程式碼潔癖的人看著縮排不舒服概念理解有偏差程式碼不夠優雅等等,希望各位可以不吝指教,不喜勿噴~

知識儲備

阮一峰老師的OAuth2.0介紹

新建microservice,作為所有服務的parent, 同時引入依賴

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <spring.cloud.dependencies.version>Greenwich.RELEASE</spring.cloud.dependencies.version>
    <spring-security-oauth2-autoconfigure.version>2.1.5.RELEASE</spring-security-oauth2-autoconfigure.version>
</properties>
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>${spring-security-oauth2-autoconfigure.version}</version>
            </dependency>
        </dependencies>
</dependencyManagement>
複製程式碼

新建uaa-service,作為認證授權服務,引入依賴

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.security.oauth.boot</groupId>
        <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        <version>2.1.5.RELEASE</version>
    </dependency>
</dependencies>
複製程式碼

spring-cloud-starter-oauth2這個依賴應該已經包含了spring security相關的jar,但是 spring-cloud-dependencies版本為Greenwich.RELEASE時,spring-security-oauth2-autoconfigure子module中引入的版本一直是2.1.0.M4,不管是重新import還是刪除本地maven repository都不管用, 在官方的issue中也有人遇到的相同的問題, 所以以上依賴暫時使用單獨引入spring-security-oauth2-autoconfigureversion還必須在子module中指定,不知你們是否也碰到這種問題.

Authorization Server 配置

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		super.configure(security);
	}

	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		clients.inMemory()
				.withClient("client-id")
				.secret(passwordEncoder.encode("client-secret"))
				.scopes("read", "write")
				.authorizedGrantTypes("password", "refresh_token")
				.authorities("user:view");
	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints
			.authenticationManager(authenticationManager)
			.tokenStore(tokenStore());
	}

	@Bean
	public TokenStore tokenStore() {
		return new InMemoryTokenStore();
	}
}
複製程式碼
  • 使用@EnableAuthorizationServer註解告訴Spring啟用authorization server
  • 同時@Configuration註解的實現了AuthorizationServerConfigurer介面的類表明這是一個authorization server配置類。
  • 這裡使用的AuthorizationServerConfigurerAdapterSpring提供的預設實現AuthorizationServerConfigurer介面的類,裡面都是空方法
  • 注入authenticationManager,這是Spring預設提供的,如果需要使用password模式,必須顯示地配置endpoints.authenticationManager(authenticationManager)
  • 一般專案中密碼之類的欄位都不會使用明文加密, 所以這裡注入passwordEncoder,用於使用者登入時密碼校驗以及建立使用者時密碼的加密
  • tokenStore這裡暫時使用InMemoryTokenStore,Spring同時也提供瞭如下幾種儲存token方式
    Spring Cloud Security OAuth2.0入門: AuthorizationServer搭建(一)
  • ClientDetailsServiceConfigurer是配置authorization server頒發的client的憑證
    • client.inMemory()是在記憶體中儲存client資訊
    • withClientsecret是client的usernamepassword
    • scopes是授權範圍,例如該client可以進行讀和寫
    • authorizedGrantTypes是配置授權方式, 可以是OAuth2.0中支援的方式,也可以是自定義的

配置使用者

@Configuration
@EnableGlobalMethodSecurity(proxyTargetClass = true, prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth
		    .inMemoryAuthentication()
		    .withUser("admin")
		    .password(passwordEncoder().encode("password"))
		    .roles("ADMIN");
	}

	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}
}
複製程式碼
  • @EnableGlobalMethodSecurity(proxyTargetClass = true, prePostEnabled = true)開啟方法級別許可權驗證
  • AuthenticationManagerBuilder在記憶體中配置一個使用者,用於password模式獲取token
  • BCryptPasswordEncoder配置加密實現類

獲取token

以上專案啟動完成之後,啟動專案,spring security會為我們提供幾個endpoint, 其中一個就是獲取token的: /oauth/token。使用的http請求工具是postman

Spring Cloud Security OAuth2.0入門: AuthorizationServer搭建(一)

如上圖所示,輸入之後,會把之前配置的clientusernamepasswordbase64編碼放在http header

Spring Cloud Security OAuth2.0入門: AuthorizationServer搭建(一)

http body中輸入

Spring Cloud Security OAuth2.0入門: AuthorizationServer搭建(一)

傳送請求之後,得到響應, 其中的access_token就是我們後續請求介面使用的令牌

總結

以上就是利用spring security簡單地搭建authorization server, 可以看到還是蠻方便的。但是如果是用在生產環境,還遠不夠,例如使用者資訊、client資訊、token資訊的持久化,各種異常的處理,資源伺服器的配置等等,在後續的文章也會不斷的完善,感謝!

相關文章