1. 程式人生 > >《SpringSecurityOauth2》 3. OAuth2 資源伺服器認證伺服器分離

《SpringSecurityOauth2》 3. OAuth2 資源伺服器認證伺服器分離

認證伺服器(9999/server)

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-oauth2</artifactId>
		</dependency>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;


/**
 * 認證伺服器  配置               認證伺服器需要配置使用者登入, 儲存使用者資訊
 */
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
	
	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private MyUserDetailsService  myUserDetailsService;
	
	@Autowired
	private TokenStore  redisTokenStore;
	
	
	/**
	 * 配置能sso登陸的客戶端
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		
		InMemoryClientDetailsServiceBuilder builder = clients.inMemory(); //記憶體
		

		//逗號分隔成陣列
		String[] authorizedGrantTypes= {"authorization_code","refresh_token","password"};
		String[] scopes= {"all","ROLE_USER"};
		
		builder.withClient("hello1")
			.secret("123456")
			.accessTokenValiditySeconds(3600)
			.autoApprove(true)
			.authorizedGrantTypes(authorizedGrantTypes)
			.scopes(scopes);
		
		builder.withClient("hello2")
		.secret("123456")
		.accessTokenValiditySeconds(3600)
		.autoApprove(true)
		.authorizedGrantTypes(authorizedGrantTypes)
		.scopes(scopes);
		
	}

	
	/**
	 * 生成令牌
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints.authenticationManager(authenticationManager).userDetailsService(myUserDetailsService)
				.tokenStore(redisTokenStore);
	}


    @Override
    public void configure(AuthorizationServerSecurityConfigurer security)
            throws Exception {
        security.tokenKeyAccess("permitAll()").checkTokenAccess(
                "isAuthenticated()").allowFormAuthenticationForClients();
    }


}

 token儲存

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

@Configuration  
public class TokenStoreConfig {
	
	@Autowired
	private RedisConnectionFactory redisConnectionFactory;
	
	
	/**
	 * 配置token儲存型別redis
	 * @return
	 */
	@Bean
	public TokenStore redisTokenStore() {
		return new RedisTokenStore(redisConnectionFactory);
	}


}

資源伺服器  (8067)

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;


/**
 * 
 * @author kevin
 *
 */
@Configuration
@EnableResourceServer	
public class MyResourceServerConfig extends ResourceServerConfigurerAdapter{
	
private static final String SERVER_RESOURCE_ID = "MyOauth2Server";
	
	@Autowired
	private TokenStore  redisTokenStore;
	
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
	
    @Bean
    public ResourceServerTokenServices tokenServices() {

        // 配置RemoteTokenServices,用於向AuththorizationServer驗證token
        RemoteTokenServices tokenServices = new RemoteTokenServices();

        // 為restTemplate配置異常處理器,忽略400錯誤,
        RestTemplate restTemplate = restTemplate();
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
            @Override
            // Ignore 400
            public void handleError(ClientHttpResponse response) throws IOException {
                if (response.getRawStatusCode() != 400) {
                    super.handleError(response);
                }
            }
        });
        tokenServices.setRestTemplate(restTemplate);
        //認證中心  spring.application.name=auth-center
        tokenServices.setCheckTokenEndpointUrl("http://auth-center:9999/server/oauth/check_token");
        //資源伺服器
        tokenServices.setClientId("hello1");
        tokenServices.setClientSecret("123456");
        return tokenServices;

    }
	 
	 
	 @Override
	 public void configure(ResourceServerSecurityConfigurer resources) {
				//resourceId 用於分配給可授予的clientId
				//stateless  標記以指示在這些資源上僅允許基於令牌的身份驗證
				//tokenStore token的儲存方式(上一章節提到)
	         resources.resourceId(SERVER_RESOURCE_ID).stateless(false).tokenStore(redisTokenStore).tokenServices(tokenServices());
	     }
	 
	 
	 

	 /**
	  * 配置哪些restful介面需要 認證,  以及許可權表示式
	  */
	@Override
	public void configure(HttpSecurity http) throws Exception {
		System.out.println("====================ResourceServerConfiguration.configure(HttpSecurity http)===================== ");
		
		http
			.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
				.and()
			.requestMatchers()
				.antMatchers("/outer/**")   //只匹配/outer/下面的
				.and()
            .authorizeRequests()
                .antMatchers("/outer/**").access("#oauth2.hasScope('all') or (!#oauth2.isOAuth() and hasRole('ROLE_USER'))")
                .anyRequest().authenticated();
            //.antMatchers("/user/**").permitAll();
	}

}

application.properties  

#設定優先ResourceServerConfigurerAdapter ,保證匹配的api先被資源伺服器攔截
security.oauth2.resource.filter-order=3

########################################################
### sso
########################################################
security.oauth2.client.clientId= hello1
security.oauth2.client.clientSecret= 123456

security.oauth2.center-url=http://localhost:9999/server

#跳轉到認證地址
security.oauth2.client.user-authorization-uri=${security.oauth2.center-url}/oauth/authorize
#獲取token路徑
security.oauth2.client.access-token-uri=${security.oauth2.center-url}/oauth/token
#獲取使用者地址
security.oauth2.resource.user-info-uri=${security.oauth2.center-url}/user/me
#token驗證
#security.oauth2.resource.token-info-uri=${security.oauth2.center-url}/oauth/check_token

########################################################
### redis
########################################################
# Redis資料庫索引(預設為0)
spring.redis.database=0
# Redis伺服器地址
spring.redis.host=192.168.3.206
#spring.redis.host=localhost
# Redis伺服器連線埠
spring.redis.port=6379
# Redis伺服器連線密碼(預設為空)
#spring.redis.password=
spring.redis.password=123456
# 連線池最大連線數(使用負值表示沒有限制)
spring.redis.pool.max-active=8
# 連線池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連線池中的最大空閒連線
spring.redis.pool.max-idle=8
# 連線池中的最小空閒連線
spring.redis.pool.min-idle=0
# 連線超時時間(毫秒)
spring.redis.timeout=0

api只有配置在資源伺服器匹配的uri下,才能通過auth2.0四種方式訪問.  如 :   /outer/**   匹配的api能通過token訪問.