一、概述
前两天在调研kafka权限这一块,根据网上的一些资料通过命令窗口也能实现用户的创建啊、权限的查看、赋予、删除等。。
但是关于java整合kafka权限这一块的资料少之又少,所以通过这些天的学习决定把自己整理的资料分享给大家。
二、kafka添加鉴权启动
这里没有做zookeeper的验证,因为懒。
所以这里正常启动zookeeper,通过admin用户启动kafka,在这里不出kafka权限配置的教程,因为如果连这步也走不到,下面就别看了。
三、添加用户曲线救国
相信这里一大部分人没有查到java如何动态添加用户。
其实这个规则是存在zookeeper上的所以kafka并没有提供Api,所以我又查阅资料发现可以通过java代码来调用linux脚本来实现这个操作。
- 在linux服务器上添加脚本
#!/bin/bash
SERVER=$1
USER=$2
PASSWORD=$3
if [ "x$SERVER" = "x" ] || [ "x$USER" = "x" ] || [ "x$PASSWORD" = "x" ]; then
echo "usage: $0 <server:port> <user> <password>"
exit
fi
/opt/software/kafka_2.11-2.2.1/bin/kafka-configs.sh --zookeeper $SERVER --alter --add-config "SCRAM-SHA-256=[iterations=8192,password=$PASSWORD],SCRAM-SHA-512=[password=$PASSWORD]" --entity-type users --entity-name $USER
- 参数说明(这不就可以通过前端页面传值了吗,)
参数 | 说明 |
zookeepers | zookeeper服务器ip:端口 |
username | 用户名 |
password | 密码 |
- java代码
这段代码要和你的脚本放在一台服务器上哈,因为要读取你的脚本
/**
* 创建用户
* 可以传递参数 用户名 密码
*/
@Test
public void createUser() throws IOException {
// broker地址
String zookeepers = "192.168.10.23:2181";
// 用户名
String username = "amao";
// 密码
String password = "amao";
// 这里是脚本地址2
ProcessBuilder pb = new ProcessBuilder("bin/create-acl-kafka-user.sh", zookeepers , username, password);
// 这里是jdk的配置,找到jdk的配置粘过来就行了
pb.environment().put("PATH", "/usr/local/java/jdk-11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin");
// 这里也是脚本地址2 (代码运行之后 就是 脚本地址2+脚本地址1 = 脚本地址)
ProcessBuilder directory = pb.redirectErrorStream(true)
.directory(new File("/opt/software/kafka_2.11-2.2.1"));
directory.start();
}
四、给用户赋予权限
以下参数均可作为传参,实例代码中直接写死
参数 | 说明 |
bootstrapServers | kafa服务器ip+端口 |
user | 要获取权限的用户名 |
aclOperation | 权限(读、写…) |
topic | 权限作用于此队列 |
groupName | 消费者组,消费者需要此参数 |
不多bb,直接上java代码
/**
* 分配权限
* 可以传递参数 服务器地址、用户名、权限类型、队列名、消费者组名
*/
@Test
public void competence() throws Exception {
// kafka服务器ip+端口,多个可用逗号隔开
private String bootstrapServers="192.168.10.23:9092";
// 用户名
private String user="cxy";
// 权限
private AclOperation aclOperation=AclOperation.READ;
// 队列名
private String topic = "test1";
// 消费者组名
private String groupName = "testConsumer";
Map<String, Object> configs = new HashMap<>();
// broker地址,多个用逗号分割
configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
// 加密信息设置
configs.put("security.protocol", "SASL_PLAINTEXT");
configs.put("sasl.mechanism", "SCRAM-SHA-512");
// 登录broker的账户 admin是管理员
configs.put("sasl.jaas.config",
"org.apache.kafka.common.security.scram.ScramLoginModule required username=\"admin\" password=\"admin\";");
KafkaAdmin admin = new KafkaAdmin(configs);
AdminClient adminClient = null;
try {
adminClient = AdminClient.create(admin.getConfig());
// principal:User:test2是需要赋予权限的帐号
// host:主机 (*号即可)
// operation:权限操作
// permissionType:权限类型
AccessControlEntry ace = new AccessControlEntry("User:"+user, "*", aclOperation, AclPermissionType.ALLOW);
// resourceType:资源类型(topic)
// name:topic名称
// patternType:资源模式类型
ResourcePattern topic = new ResourcePattern(ResourceType.TOPIC, topic, PatternType.LITERAL);
ResourcePattern group = new ResourcePattern(ResourceType.GROUP, groupName, PatternType.LITERAL);
// 给队列权限
AclBinding topicAcl = new AclBinding(topic, ace);
// 给消费者组权限,生产者去掉就行了
AclBinding groupAcl = new AclBinding(group, ace);
ArrayList<AclBinding> ab = new ArrayList<>();
ab.add(topicAcl);
ab.add(groupAcl);
// 多个权限赋予可以传list
adminClient.createAcls(ab);
} catch (Exception e) {
throw new Exception(e);
} finally {
if (ObjectUtil.isNotNull(adminClient)) {
adminClient.close();
}
}
}
五、重置offset
参数 | 说明 |
bootstrapServers | kafa服务器ip+端口 |
topic | 队列 |
groupName | 消费者组 |
offset | 偏移量 |
partitionInfo | 分区 |
/**
* 重置offset前,消息监听方需要暂停服务
* 可以传递参数 服务器地址、队列名、偏移量、消费者组、分区
*/
@Test
public void resetOffset() {
// kafka服务器ip+端口,多个可用逗号隔开
private String bootstrapServers="192.168.10.23:9092";
// 队列名
private String topic = "test1";
// 消费者组名
private String groupName = "testConsumer";
// 偏移量
private long offset = 1500L;
// 分片
private short partitionInfo = 1;
Properties props = new Properties();
// 服务器ip:端口号,集群用逗号分隔
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
// 消费者指定组,名称可以随意,注意相同消费组中的消费者只能对同一个分区消费一次
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupName);
// 是否启用自动提交,默认true
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
//重启时未消费得数据不再进行消费
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
// key反序列化指定类
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// value反序列化指定类,注意生产者与消费者要保持一致,否则解析出问题
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 1);
props.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, 30000);
// 加密信息设置
props.put("security.protocol", "SASL_PLAINTEXT");
props.put("sasl.mechanism", "SCRAM-SHA-512");
props.put("sasl.jaas.config",
"org.apache.kafka.common.security.scram.ScramLoginModule required username=\"admin\" password=\"admin\";");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
// 所有分区都改
// List<PartitionInfo> aa = consumer.partitionsFor(topic);
// Map map = new HashMap();
// for (int i = 0; i < aa.size(); i++) {
// map.put(new TopicPartition(topic, partitionInfo), new OffsetAndMetadata(offset));
// }
map.put(new TopicPartition(topic, partitionInfo), new OffsetAndMetadata(offset));
consumer.commitSync(map);
System.out.println("设置完成~~~~~~" + aa.size());
}
创作不易大家记得点赞啊!!