Java连接Kerberos认证的Kafak

Java:甲。Kafka:乙。

一、一般需要三个文件。xxx.keytab ,xxkrb5.conf , 创建的 jaas.conf,并配置hosts。

1、连谁让谁提供 xxx.keytab文件,进行身份验证(该文件由乙提供)。

2、添加krb5.conf文件,可直接从kdc所在服务器复制(内容由乙提供)。

#配置片段也可以放在此目录中 /etc/krb5.conf.d/
[logging]
         default = FILE:/var/log/krb5libs.log
         kdc = FILE:/var/log/krb5kdc.log
         admin_server = FILE:/var/log/kadmind.log
[libdefaults]
         default_realm = ABC.COM    # 指定默认领域名
         dns_lookup_realm = false   #  指定无需DNS解析领域请求包
         dns_lookup_kdc = ture      #  指定允许DNS解析kdc请求包
ticket_lifetime = 24h               #  指定Kerberos认证票证有效期
         forwardable = yes          #  允许转发解析请求
[realms]  
          ABC.COM = {
          kdc = 192.168.67.130:88        # 指定KDC服务器和KDC服务端口
          admin_server = 192.168.67.129  #  指定域控制器和管理端口
          default_domain = abc.com       #  指定默认域
         } 

[domain_realm]
         .abc.com = ABC.COM
          abc.com = ABC.COM
#  以上两条其实是设置一个领域搜索范围,并通过这两个语句可以使得领域名与大小写无关。

3、创建 jaas.conf文件,并添加内容

KafkaServer {  
    com.sun.security.auth.module.Krb5LoginModule required  
    useKeyTab=true 
    keyTab="D:/kafka/xxx.keytab"  #指定”乙“已经给的xxx.keytab文件。
    storeKey=true  
    useTicketCache=false  
    principal="uname@ABC.COM";  #uname是berberos认证的用户名。ABC.COM 是认领域名。
};
KafkaClient {  
    com.sun.security.auth.module.Krb5LoginModule required  
    useKeyTab=true  
    keyTab="D:/kafka/xxx.keytab"  
    storeKey=true  
    useTicketCache=false  
    principal="uname@ABC.COM"; 
};
Client {  
    com.sun.security.auth.module.Krb5LoginModule required  
    useKeyTab=true  
    storeKey=true 
    useTicketCache=false  
    keyTab="D:/kafk/xxx.keytab"  
    principal="uname@ABC.COM"; 
};

4、本地配置hosts 

hosts位置一般都是在C:\Windows\System32\drivers\etc 目录下。

java kerberos 链接kafka java kerberos认证_java

编辑hosts,把连接用到的ip和hostname都配置上。

java kerberos 链接kafka java kerberos认证_kafka_02

 

二、生产者连接Kerberos认证的kafka

 认证主要看代码注释的 “一”和“二”。

import java.util.Properties;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.Callback;
import org.apache.kafka.clients.producer.RecordMetadata;

public class CallBackProducer {
	
	public static void main(String[] args) {
		//一、*****添加认证
        System.setProperty("java.security.auth.login.config","D:\\kafka\\jaas.conf");
        System.setProperty("java.security.krb5.conf","D:\\kafka\\krb5.conf");
		
        System.setProperty("javax.security.auth.useSubjectCredsOnly", "true");
		//1、创建kafka集群配置信息
		Properties properties = new Properties();
		//连接kafka集群
		//properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.67.128:9092,192.168.67.129:9092,192.168.67.130:9092");
		
		//序列号key和value(必须有)
		properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
		properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
		
		//二、*****配置安全协议security.protocol和sasl.kerberos.service.name
		//这俩行如果丢了的话,日志会一直打印,消息也没有发送出去。
		properties.put("security.protocol", "SASL_PLAINTEXT");//安全协议
		properties.put("sasl.kerberos.service.name", "kafka");
		
		
		//2、创建生产者对象
		 KafkaProducer<String,String> producer = new KafkaProducer<String,String>(properties);
		
		//3、发送消息
		 for (int i = 0; i <7; i++) {
				//通过send方法,初始化ProducerRecord()。
				producer.send(new ProducerRecord<String, String>("topicName","发送消息"+i),new Callback() {
					public void onCompletion(RecordMetadata arg0, Exception arg1) {
						if(arg1==null){
							System.err.println("发送成功:"+arg0.topic()+":"+arg0.partition()+":"+arg0.offset());
						}else{
							System.err.println("发送失败");
						}
					}
				});
			}
		
		//4、关闭资源
		producer.close();
	}
	
}

 如果能正常发送消息,说明生产者已经连接成功。否则检查一下文件配置是否有问题。

注意:Java代码认证连接kafka 不可丢掉的代码:

//一、*****添加认证
        System.setProperty("java.security.auth.login.config","D:\\kafka\\jaas.conf");
        System.setProperty("java.security.krb5.conf","D:\\kafka\\krb5.conf");

//二、*****配置安全协议security.protocol和sasl.kerberos.service.name
		//这俩行如果丢了的话,日志会一直打印,消息也没有发送出去。
		properties.put("security.protocol", "SASL_PLAINTEXT");//安全协议
		properties.put("sasl.kerberos.service.name", "kafka");

 三、消费者连接Kerberos认证的kafka

与生产者一样认证主要看代码注释的 “一”和“二”。不能丢掉。

注意:代码中测试消费者消费之前最好先执行一下生产者代码。先生产消息再消费,否则可能消费者会一直打印日志而且消费不到消息。

import java.util.Arrays;
import java.util.Properties;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;

public class MyConsumer {
	public static void main(String[] args) {
		//一、*****添加认证
		System.setProperty("java.security.krb5.conf", "D:\\WorkOffice\\JBK\\kerberosKafka\\dev_krb5.conf");
        System.setProperty("java.security.auth.login.config", "D:\\WorkOffice\\JBK\\kerberosKafka\\jaas.conf");
        //System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
		
		//1、创建配置信息
		Properties properties = new Properties();
		//连接集群(必须有)
		//properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"kafka01:9092,kafka02:9092,kafka03:9092");
		//开启自动提交。如果不开启自动提交,需要设置手动提交。
		properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,true);
		//设置自动提交时间,默认1000毫秒,也就是1秒。当不开启自动提交ENABLE_AUTO_COMMIT_CONFIG=false时,该配置无效。
		properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,1000);
		
		//key和value的反序列号(必须有)
		properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
		properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
		
		//二、*****配置安全协议security.protocol和sasl.kerberos.service.name
		properties.put("security.protocol", "SASL_PLAINTEXT");
		properties.put("sasl.kerberos.service.name", "kafka");
		//消费者组,必填
		properties.put(ConsumerConfig.GROUP_ID_CONFIG," group01");
		
		
		//2、创建consumer对象
		KafkaConsumer<String,String> consumer = new KafkaConsumer<String,String>(properties);
		
		//3、订阅主题,因为每个消费者可以订阅多个主题,所以传的list。
		consumer.subscribe(Arrays.asList("topicName"));
		
		while(true){
			//4、拉取消息,并设置等待时间 ,单位ms。因为一次可以拉取多条数据,所以是ConsumerRecords,后边加了 s。
			ConsumerRecords<String, String> poll = consumer.poll(1000);
			//5、遍历ConsumerRecords获取对象信息
			for (ConsumerRecord<String, String> consumerRecord : poll) {
				System.err.println("消费者:"+consumerRecord.topic()+",分区:"+consumerRecord.partition()+",key:"+consumerRecord.key()+",value:"+consumerRecord.value()+",offset:"+consumerRecord.offset());
			}
			
		}
	}
}

注意:Java代码认证连接kafka 不可丢掉的代码: 

//一、*****添加认证
        System.setProperty("java.security.auth.login.config","D:\\kafka\\jaas.conf");
        System.setProperty("java.security.krb5.conf","D:\\kafka\\krb5.conf");

//二、*****配置安全协议security.protocol和sasl.kerberos.service.name
		//这俩行如果丢了的话,日志会一直打印,消息也没有发送出去。
		properties.put("security.protocol", "SASL_PLAINTEXT");//安全协议
		properties.put("sasl.kerberos.service.name", "kafka");