最近在学习Spring cloud微服务的搭建,采用Spring 的 OAuth2作为单点登录服务器,通过zuul作统一路由,所以认证服务 (Authentication Server)端可通过多实例进行集群部署,集群部署时需要对认证服务 (Authentication Server)进行如下几点配置。

1、通过redis存储AccessToken

 

@Configuration
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
        @Autowired
	private AuthenticationManager authenticationManager;
        @Autowired
	private RedisConnectionFactory redisConnectionFactory;
        @Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints.authenticationManager(authenticationManager).accessTokenConverter(jwtAccessTokenConverter());
		endpoints.tokenStore(tokenStore());
	}
	

	@Bean
	public TokenStore tokenStore() {
		return new RedisTokenStore(redisConnectionFactory);
	}


}


2、共享Authentication code

 

目前spring提供了内存和数据库两种方式存储授权码Authentication code,要实现多个实例之间共享可以选在将AuthenTicationCode存储在数据中,相关配置为

 

        @Bean
	public AuthorizationCodeServices authorizationCodeServices(){
		return new JdbcAuthorizationCodeServices(dataSource);
	}

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

需要在数据库中创建表 auth_code

 

 

CREATE TABLE `oauth_code` (
  `code` varchar(1024) DEFAULT NULL,
  `authentication` blob
)

我们也可以自定义AuthorizationCodeServices实现类来将auth_code 存放在redis中

 

 

public class RedisAuthenticationCodeServices extends RandomValueAuthorizationCodeServices {
	private static Logger log = Logger.getLogger(RedisAuthenticationCodeServices.class);
	private static final String AUTH_CODE_KEY = "auth_code";
	private RedisConnectionFactory connectionFactory;

	public RedisAuthenticationCodeServices(RedisConnectionFactory connectionFactory) {
		Assert.notNull(connectionFactory, "RedisConnectionFactory required");
		this.connectionFactory = connectionFactory;
	}

	@Override
	protected OAuth2Authentication remove(String code) {
		RedisConnection conn = getConnection();
		try {
			OAuth2Authentication authentication = null;

			try {
				authentication = SerializationUtils
						.deserialize(conn.hGet(AUTH_CODE_KEY.getBytes("utf-8"), code.getBytes("utf-8")));
			} catch (Exception e) {
				return null;
			}

			if (null != authentication) {
				conn.hDel(AUTH_CODE_KEY.getBytes("utf-8"), code.getBytes("utf-8"));
			}

			return authentication;
		} catch (Exception e) {
			return null;
		} finally {
			conn.close();
		}
	}

	@Override
	protected void store(String code, OAuth2Authentication authentication) {
		RedisConnection conn = getConnection();
		try {
			conn.hSet(AUTH_CODE_KEY.getBytes("utf-8"), code.getBytes("utf-8"),
					SerializationUtils.serialize(authentication));
		} catch (Exception e) {
			log.error("保存authentication code 失败", e);
		} finally {
			conn.close();
		}

	}

	private RedisConnection getConnection() {
		return connectionFactory.getConnection();
	}

}


3、共享session

 

OAuth2服务在申请授权码时会先判断用户是否登录,如未登录则会引导到登录页面,所以我们需要在不同实例之间共享session,我么可以通过Spring的Session很容易的实现session共享。首先引入jar包,maven的配置如下

 

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session</artifactId>
</dependency>

通过@EnableRedisHttpSession注解开启session共享。



 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐