《SpringSecurityOauth2》 3. OAuth2 資源伺服器認證伺服器分離
阿新 • • 發佈:2018-12-24
認證伺服器(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訪問.