在使用客户端程序连接数据库时,您可以启用TLS(SSL)加密功能提高数据链路的安全性,保障数据的完整性。您可以根据自身应用特点选用任何兼容Redis协议的客户端程序。本文列举一些常见的客户端程序的代码示例,帮助您快速连接。
前提条件
实例已开启TLS(SSL)加密,具体操作参见开启TLS加密。
客户端部署在与Redis实例相同专有网络(VPC)的ECS实例上。
注意事项
准备工作
将客户端所在的ECS内网IP地址添加至Redis实例的白名单中,具体操作请参见设置白名单。
获取以下信息并设置在客户端程序的代码中:
需获取的信息
获取方式
实例的连接地址
Redis实例支持多种连接地址,推荐使用专有网络连接,可获得更高的安全性和更低的网络延迟。更多信息,请参见查看连接地址。
端口号
端口号默认为6379,您也可以自定义端口号。具体操作,请参见修改连接地址或端口。
实例的账号(部分客户端程序无需设置)
Redis实例默认会创建一个以实例ID命名的账号(例如r-bp10noxlhcoim2****),您也可以创建一个新的账号并赋予权限。更多信息,请参见创建与管理账号。
账号的密码
根据选取账号的不同,密码的填写格式有一定区别:
默认账号(以实例ID命名的账号):直接填写密码即可。
新创建的账号:密码格式为
<user>:<password>
。例如自定义账号为testaccount
,密码为Rp829dlwa
,密码需填写为testaccount:Rp829dlwa
。
说明如果通过第三方数据库管理工具(例如RDM等)连接Redis实例,请在密码框中输入
user:password
进行连接。如果忘记密码,您可以重置密码。具体操作,请参见修改或重置密码。
下载CA证书,请参见开启TLS加密。
redis-cli
您需要在编译Redis时,指定BUILD_TLS=yes
,才能在redis-cli中启用TLS连接Redis实例。
登录ECS实例,下载、安装redis-cli。
执行下述命令,安装相关依赖。
yum install openssl-devel gcc
- 执行下述命令下载Redis源码文件。
wget https://download.redis.io/releases/redis-7.0.0.tar.gz
说明 本文以redis-7.0.0版本为例演示操作流程,您也可以安装其他版本。具体操作,请参见Redis官网。 - 执行下述命令解压Redis源码文件。
tar xzf redis-7.0.0.tar.gz
执行下述命令进入解压后的目录,编译安装Redis源码文件并开启TLS。
cd redis-7.0.0&&make BUILD_TLS=yes
编译安装需要一段时间(通常为2分钟~3分钟)。
在命令行窗口执行下述命令连接实例。
./src/redis-cli -h r-bp14joyeihew30****.redis.rds.aliyuncs.com -p 6379 --tls --cacert ./ApsaraDB-CA-Chain.pem
cacert后需指定CA证书的路径。
执行下述命令完成密码验证。
AUTH password
显示OK表示已成功连接实例。
Java
下述示例代码以Jedis 3.6.0版本为例,推荐使用最新版本。
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class JedisSSLTest {
private static SSLSocketFactory createTrustStoreSSLSocketFactory(String jksFile) throws Exception {
KeyStore trustStore = KeyStore.getInstance("jks");
InputStream inputStream = null;
try {
inputStream = new FileInputStream(jksFile);
trustStore.load(inputStream, null);
} finally {
inputStream.close();
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
return sslContext.getSocketFactory();
}
public static void main(String[] args) throws Exception {
// ApsaraDB-CA-Chain.jks为证书文件名称。
final SSLSocketFactory sslSocketFactory = createTrustStoreSSLSocketFactory("ApsaraDB-CA-Chain.jks");
// 连接池的设置分别为实例的连接地址、端口号、超时设置、密码。
JedisPool pool = new JedisPool(new GenericObjectPoolConfig(), "r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com",
6379, 2000, "redistest:Test1234", 0, true, sslSocketFactory, null, null);
try (Jedis jedis = pool.getResource()) {
jedis.set("key", "value");
System.out.println(jedis.get("key"));
}
}
}
Python
下述示例代码以redis-py客户端为例,推荐使用最新版本。
连接池连接
#!/bin/python
import redis
# 设置连接池,分别将host、port、password的值分别替换为实例的连接地址、端口号、密码。
# ApsaraDB-CA-Chain.pem为证书文件名称。
pool = redis.ConnectionPool(connection_class=redis.connection.SSLConnection, max_connections=100,
host="r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com", port=6379, password="redistest:Test1234",
ssl_cert_reqs=True, ssl_ca_certs="ApsaraDB-CA-Chain.pem")
client = redis.Redis(connection_pool=pool)
client.set("hi", "redis")
print client.get("hi")
普通连接
#!/bin/python
import redis
# 设置连接信息,分别将host、port、password的值分别替换为实例的连接地址、端口号、密码。
# ApsaraDB-CA-Chain.pem为证书文件名称。
client = redis.Redis(host="r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com", port=6379,
password="redistest:Test1234", ssl=True,
ssl_cert_reqs="required", ssl_ca_certs="ApsaraDB-CA-Chain.pem")
client.set("hello", "world")
print client.get("hello")
PHP
以下示例以predis客户端为例,推荐使用最新版本。如果您使用的是phpredis客户端,连接示例请参见此issue。
<?php
require __DIR__.'/predis/autoload.php';
/* 设置连接信息,分别将host、port、password的值分别替换为实例的连接地址、端口号、密码
ApsaraDB-CA-Chain.pem为证书文件名称*/
$client = new Predis\Client([
'scheme' => 'tls',
'host' => 'r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com',
'port' => 6379,
'password' => 'redistest:Test1234',
'ssl' => ['cafile' => 'ApsaraDB-CA-Chain.pem', 'verify_peer' => true],
]);
/* 依次替换下述代码中的连接地址和端口 */
//$client = new Predis\Client('tls://r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com:6379?ssl[cafile]=ApsaraDB-CA-Chain.pem&ssl[verify_peer]=1');
$client->set("hello", "world");
print $client->get("hello")."\n";
?>
C#
以下示例以StackExchange.Redis客户端为例,推荐使用最新版本。
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using StackExchange.Redis;
namespace SSLTest
{
class Program
{
private static bool CheckServerCertificate(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
var ca = new X509Certificate2(
"/your path/ApsaraDB-CA-Chain/ApsaraDB-CA-Chain.pem");
return chain.ChainElements
.Cast<X509ChainElement>()
.Any(x => x.Certificate.Thumbprint == ca.Thumbprint);
}
static void Main(string[] args)
{
// 设置连接信息,分别将host、port、password的值分别替换为实例的连接地址、端口号、密码。
// ApsaraDB-CA-Chain.pem为证书文件名称。
ConfigurationOptions config = new ConfigurationOptions()
{
EndPoints = {"r-bp10q23zyfriodu*****.redis.rds.aliyuncs.com:6379"},
Password = "redistest:Test1234",
Ssl = true,
};
config.CertificateValidation += CheckServerCertificate;
using (var conn = ConnectionMultiplexer.Connect(config))
{
Console.WriteLine("connected");
var db = conn.GetDatabase();
db.StringSet("hello", "world");
Console.WriteLine(db.StringGet("hello"));
}
}
}
}
Spring Data Redis
以下示例以Spring Data Redis 2.7.12版(Java 1.8版本)为例,推荐使用最新版本。
@Configuration
public class RedisConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
// 建议您将TLS证书配置存放在properties文件中。
String host = "r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com";
int port = 6379;
String password = "xxx";
String trustStoreFilePath = "/path/to/ApsaraDB-CA-Chain.jks";
ClientOptions clientOptions = ClientOptions.builder().sslOptions(
SslOptions.builder().jdkSslProvider().truststore(new File(trustStoreFilePath)).build()).build();
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setPassword(password);
LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
.clientOptions(clientOptions)
.useSsl().build();
return new LettuceConnectionFactory(config, lettuceClientConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
Lettuce
以下示例以Lettuce 6.2.4.RELEASE版本为例,推荐使用最新版本。
public class SSLExample {
public static void main(String[] args) throws Exception {
String host = "r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com";
int port = 6379;
String password = "xxxx";
String trustStoreFilePath = "/path/to/ApsaraDB-CA-Chain.jks";
RedisURI uri = RedisURI.builder()
.withHost(host)
.withPort(port)
.withPassword(password.toCharArray())
.withSsl(true).build();
SslOptions sslOptions = SslOptions.builder()
.jdkSslProvider()
.truststore(new File(trustStoreFilePath)).build();
ClientOptions clientOptions = ClientOptions.builder()
.sslOptions(sslOptions).build();
RedisClient client = RedisClient.create(uri);
client.setOptions(clientOptions);
RedisCommands<String, String> sync = client.connect().sync();
System.out.println(sync.set("key", "value"));
System.out.println(sync.get("key"));
}
}