1.架構圖
技術團隊通過一段時間的積累后,我們打算對往后的一些新項目采用Spring Cloud技術棧來實現。大概微服務的架構如下:
- Euraka注冊中心集群
- Zuul網關集群
- 各模塊微服務集群
- Nginx實現負載均衡
- Spring Cloud Config 統一配置中心
- Monitor微服務監控
2.注冊中心
注冊中心很簡單,這里主要說一下注冊中心的高可用配置‘
這里看到我設置了node-1,node-2兩個配置文件,就是在啟動應用的時候,分別啟動不同的配置。
node-1的端口為9010,並向node-2注冊,配置如下:
server: port: 9010 spring: application: name: register ##name必須一樣,不然高可用會導致unavailable-replicas eureka: instance: hostname: register1 client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://register2:9011/eureka/
node-2的端口為9011,並向node-1注冊,配置如下:
server: port: 9011 spring: application: name: register ##name必須一樣,不然高可用會導致unavailable-replicas eureka: instance: hostname: register2 client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://register2:9010/eureka/
這里注意一下:spring.application.name需要一致,不然會出現unavailable-replicas的情況
3.OAUTH2認證服務器
我這里采用認證服務器與資源服務器分離的方式。
3.1 oauth2 server 配置
我采取了數據庫和redis兩種方式來存儲token,可以方便切換,生成環境下建議使用redis方式。
AuthorizationServer:
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Autowired private DataSource dataSource;
@Autowired private UserDetailsServiceImpl userDetailsService; @Autowired private RedisConnectionFactory redisConnectionFactory; @Bean RedisTokenStore redisTokenStore(){ return new RedisTokenStore(redisConnectionFactory); }
token存儲數據庫
// @Bean // public JdbcTokenStore jdbcTokenStore(){ // return new JdbcTokenStore(dataSource); // } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetails()); }
@Bean public ClientDetailsService clientDetails() { return new JdbcClientDetailsService(dataSource); }
@Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(redisTokenStore()) .userDetailsService(userDetailsService) .authenticationManager(authenticationManager); endpoints.tokenServices(defaultTokenServices()); }
/** * <p>注意,自定義TokenServices的時候,需要設置@Primary,否則報錯,</p> * @return */ @Primary @Bean public DefaultTokenServices defaultTokenServices(){ DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setTokenStore(redisTokenStore()); tokenServices.setSupportRefreshToken(true); tokenServices.setClientDetailsService(clientDetails()); tokenServices.setAccessTokenValiditySeconds(60*60*12); // token有效期自定義設置,默認12小時 tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);//默認30天,這里修改 return tokenServices; } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.tokenKeyAccess("permitAll()"); security .checkTokenAccess("isAuthenticated()"); security.allowFormAuthenticationForClients(); } }
WebSecurityConfig:
@Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private UserDetailsServiceImpl userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().and() .csrf().disable() .httpBasic(); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/favor.ioc"); } }
3.2 ResourceServer
因為我們認證中心會提供User信息,所以也是資源服務器。
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter{ @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable() .exceptionHandling() .authenticationEntryPoint(new Http401AuthenticationEntryPoint("Bearer realm=\"webrealm\"")) .and() .authorizeRequests().anyRequest().authenticated() .and() .httpBasic(); } }
4.資源服務器 Resource
ResourceServer:
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable() .exceptionHandling() .authenticationEntryPoint(new Http401AuthenticationEntryPoint("Bearer realm=\"webrealm\"")) .and() .authorizeRequests().anyRequest().authenticated() .and() .httpBasic(); } }
主要是application.yml的配置
security: oauth2: resource: id: resource user-info-uri: http://10.10.8.2:9030/uaa/user prefer-token-info: false
5.Zuul網關
5.1開啟支持Sso
@Configuration @EnableOAuth2Sso public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); } }
5.2配置
spring: application: name: Gateway zipkin: base-url: http://10.10.8.2:9050 server: port: 9030 eureka: instance: prefer-ip-address: true #使用IP注冊 instance-id: ${spring.cloud.client.ipAddress}:${server.port} client: service-url: defaultZone: http://register1:9010/eureka/,http://register2:9011/eureka/ ###actuator監控點 start#### endpoints: health: sensitive: false enabled: true ##默認情況下很多端點是不允許訪問的,會返回401:Unauthorized management: security: enabled: false ###actuator監控點 end#### zuul: host: connect-timeout-millis: 10000 socket-timeout-millis: 60000 routes: uaa: path: /uaa/** strip-prefix: true sensitiveHeaders: serviceId: auth2.0-center security: basic: enabled: false oauth2: client: access-token-uri: http://10.10.8.2:9030/uaa/oauth/token ##網關的地址 user-authorization-uri: http://10.10.8.2:9030/uaa/oauth/authorize resource: user-info-uri: http://10.10.8.2:9030/uaa/user prefer-token-info: false ##############end##################### ####超時配置#### ribbon: ReadTimeout: 10000 ConnectTimeout: 10000 MaxAutoRetries: 1 MaxAutoRetriesNextServer: 2 eureka: enabled: true hystrix: command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 600000 ###超時配置###
6.展示
分別啟動register、auth-center、gateway、resource。效果如下:
6.1獲取access_token
6.2刷新token
6.3用access_token獲取資源
7.結束
到這里Spring Cloud OAUTH2.0統一認證的骨架就完成了,具體項目拿過來修改就可以滿足項目的需求了。