最近在学习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共享。
因篇幅问题不能全部显示,请点此查看更多更全内容