一、概述

1、Kafka的权限分类

1)、身份认证(Authentication):对client 与服务器的连接进行身份认证,brokers和zookeeper之间的连接进行Authentication(producer 和 consumer)、其他 brokers、tools与 brokers 之间连接的认证。

2)、权限控制(Authorization):实现对于消息级别的权限控制,clients的读写操作进行Authorization:(生产/消费/group)数据权限。

2、实现方式

自0.9.0.0版本开始Kafka社区添加了许多功能用于提高Kafka群集的安全性,Kafka提供SSL或者SASL两种安全策略。SSL方式主要是通过CA令牌实现,此文主要介绍SASL方式。

1)SASL验证:

验证方式

Kafka版本

特点


SASL/PLAIN



0.10.0.0



不能动态增加用户



SASL/SCRAM



0.10.2.0



可以动态增加用户



SASL/Kerberos



0.9.0.0



需要独立部署验证服务



SASL/OAUTHBEARER



2.0.0



需自己实现接口实现token的创建和验证,需要额外Oauth服务


2)SSL加密: 使用SSL加密在代理和客户端之间,代理之间或代理和工具之间传输的数据。

二、使用SASL进行身份验证

1、SASL/PLAIN验证

1.1 版本

相关包

版本

下载地址


Kafka



0.11.0.0



http://kafka.apache.org/downloads



Zookeeper



3.4.8



https://www.apache.org/dyn/closer.cgi/zookeeper/


1.2 Zookeeper配置

1)修改zoo.cfg增加两行配置:

authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
requireClientAuthScheme=sasl

2)配置JAAS文件:

Server {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="admin-sec"
};

说明:定义了需要链接到Zookeeper服务器的用户名和密码

3)加入需要的包:

kafka-clients-0.10.0.1.jar
lz4-1.3.0.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.21.jar
snappy-java-1.1.2.6.jar

如果没有引入对应的kafka包,启动kafka时会报找不到org.apache.kafka.common.security.plain.PlainLoginModule包的错误。

Zookeeper引入加载包需改Zookeeper脚本zkEnv.sh,在最后加入:

for i in "$ZOOBINDIR"/../for_sasl/*.jar; do
  CLASSPATH="$i:$CLASSPATH"
done
SERVER_JVMFLAGS=" -Djava.security.auth.login.config=$ZOOCFGDIR/zk_server_jaas.conf "

将for_sasl目录下的所有jar文件追加到CLASSPATH变量,再设置一个JVM参数给SERVER_JVMFLAGS变量,这两个变量都会在Zookeeper启动时传给JVM。

4)启动Zookeeper

bin/zkServer.sh start

1.3 Kafka服务端配置

1)kafka增加认证信息:

创建JAAS文件:

KafkaServer {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="admin-sec"
user_admin="admin-sec"
user_producer="prod-sec"
user_consumer="cons-sec";
};

user_XXX 为自定义的用户,所有可以使用的用户必须在此定义,不能再之后新增。

  • producer用于开放生产权限。
  • consumer用于开放消费权限。

JAAS文件定义了链接Kafka Broker时所需要的用户名密码及broker各个节点之间相互通信的用户名密码:

  • username/ password:broker之间通信使用的用户名密码。
  • user_admin/user_producer/user_consumer:客户端(管理员、生产者、消费者)链接broker时所使用到的用户名密码。

2)配置server.properties

listeners=SASL_PLAINTEXT://主机名称:9092
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
allow.everyone.if.no.acl.found=true     //当没有找到ACL配置时,允许所有的访问操作。

3)修改启动脚本

exec $base_dir/kafka-run-class.sh 
$EXTRA_ARGS -Djava.security.auth.login.config
=/home/qa/Downloads/kafka_2.12-0.11.0.1/config/kafka_server_jaas.conf kafka.Kafka "$@"

1.4 Kafka客户端端配置

1)创建JAAS文件:消费者:kafka_client_consumer_jaas.conf

KafkaClient {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="consumer"
password="cons-sec";
};

生产者:kafka_client_producer_jaas.conf

KafkaClient {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="producer"
password="prod-sec";
};

2)修改客户端配置信息:分别在producer.properties和consumer.properties添加认证机制

security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN

consumer.properties中额外加入分组配置

group.id=test-group

3)修改客户端脚本指定JAAS文件加载:

export KAFKA_HEAP_OPTS="-Xmx512M -Djava.security.auth.login.config=/home/kafka_client_jaas.conf"

1.5 授权

此时已经完成了基本的配置,但是如果测试可以发现无论是生产还是消费,都不被允许。最后一步,我们需要为设置的账号授权。

1)创建主题:

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 4 --topic test

2)增加生产权限:

./kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer
 --authorizer-properties zookeeper.connect=localhost:2181 
--add --allow-principal User:producer --operation Write --topic test

3)配置消费权限:

bin/kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer
--authorizer-properties zookeeper.connect=localhost:2181 --add
 --allow-principal User:consumer --operation Read --topic test

4)配置消费分组权限:

bin/kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer
--authorizer-properties zookeeper.connect=localhost:2181 --add 
--allow-principal User:consumer --operation Read --group test-group

5)生产数据:

./kafka-console-producer-acl.sh --broker-list 127.0.0.1:9092 --topic test

6)消费数据:

bin/kafka-console-consumer-acl.sh --bootstrap-server  127.0.0.1:9092 
--topic test --from-beginning --consumer.config ./config/consumer.properties

我们可以查看配置的权限信息:

bin/kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer 
--authorizer-properties zookeeper.connect=localhost:2181 --list

Current ACLs for resource Topic:test: User:producer has Allow permission for operations: Write from hosts: * User:consumer has Allow permission for operations: Read from hosts: * Current ACLs for resource Group:test-group: User:consumer has Allow permission for operations: Read from hosts: *

1.6 JAVA客户端

在消费者/生产者初始化属性中引入JAAS文件:

static{
System.setProperty("java.security.auth.login.config","D://demoPeoject//JpaTest//src//main//resources//kafka_client_scram_consumer_jaas.conf");
}
properties.put("security.protocol", "SASL_PLAINTEXT");
properties.put("sasl.mechanism", "SCRAM-SHA-256");

2、SASL/SCRAM验证

上一节,我们通过配置SASL/PLAIN验证,实现了对Kafka的权限控制。但SASL/PLAIN验证有一个问题:只能在JAAS文件KafkaServer中配置用户,一但Kafka启动,无法动态新增用户。

SASL/SCRAM验证可以动态新增用户并分配权限。

2.1 版本

同上文

2.2 启动Zookeeper和Kafka

此方法是把凭证(credential)存储在Zookeeper,可以使用kafka-configs.sh在Zookeeper中创建凭据。对于每个SCRAM机制,必须添加具有机制名称的配置来创建凭证,在启动Kafka broker之前创建代理间通信的凭据。

所以第一步,在没有设置任何权限的配置下启动Kafka和Zookeeper。

2.3 创建SCRAM证书

1)创建broker建通信用户:admin(在使用sasl之前必须先创建,否则启动报错)

bin/kafka-configs.sh --zookeeper 127.0.0.1:2181 --alter 
--add-config 'SCRAM-SHA-256=[password=admin-sec],
SCRAM-SHA-512=[password=admin-sec]' --entity-type users --entity-name admin

2)创建生产用户:producer

bin/kafka-configs.sh --zookeeper 127.0.0.1:2181 --alter 
--add-config 'SCRAM-SHA-256=[iterations=8192,password=prod-sec],
SCRAM-SHA-512=[password=prod-sec]' --entity-type users --entity-name producer

3)创建消费用户:consumer

bin/kafka-configs.sh --zookeeper 127.0.0.1:2181 --alter 
--add-config 'SCRAM-SHA-256=[iterations=8192,password=cons-sec],
SCRAM-SHA-512=[password=cons-sec]' --entity-type users --entity-name consumer

SCRAM-SHA-256/SCRAM-SHA-512是对密码加密的算法,二者有其一即可。

2.4 查看SCRAM证书

bin/kafka-configs.sh --zookeeper localhost:2181 --describe --entity-type users --entity-name consumer
bin/kafka-configs.sh --zookeeper localhost:2181 --describe --entity-type users --entity-name producer

2.5 删除SCRAM证书

bin/kafka-configs.sh --zookeeper localhost:2181 --alter --delete-config 'SCRAM-SHA-512' 
--delete-config 'SCRAM-SHA-256' --entity-type users --entity-name producer

2.6 服务端配置

在用户证书创建完毕之后开始Kafka服务端的配置:

1)创建JAAS文件:

KafkaServer {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="admin"
password="admin-sec";
};

2)将JAAS配置文件位置作为JVM参数传递给每个Kafka Broker

exec $base_dir/kafka-run-class.sh 
$EXTRA_ARGS -Djava.security.auth.login.config
=/home/qa/Downloads/kafka_2.12-0.11.0.1/config/kafka_server_jaas.conf kafka.Kafka "$@"

3)配置server.properties:

认证配置
listeners=SASL_PLAINTEXT://主机名称:9092
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-256
sasl.enabled.mechanisms=SCRAM-SHA-256
ACL配置
allow.everyone.if.no.acl.found=false
super.users=User:admin
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer

可以根据自己的需求选择SASL_SSL或SASL_PLAINTEXT, PLAINTEXT为不加密明文传输,性能好与SSL

4)重启Kafka和Zookeeper

2.7 客户端配置

1)为我们创建的三个用户分别创建三个JAAS文件:

KafkaClient {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="admin"
password="admin-sec";
};
KafkaClient {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="consumer"
password="cons-sec";
};
KafkaClient {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="producer"
password="prod-sec";
};

2)修改启动脚本引入JAAS文件:

以生产者为例:

exec $(dirname $0)/kafka-run-class.sh 
-Djava.security.auth.login.config=/home/qa/Downloads/kafka_2.12-0.11.0.1/config/kafka_client_scram_producer_jaas.conf

3)ACL权限配置:此时如果我们生产数据则会发生如下错误:

kafka认证方式 java 配置 kafka用户认证_客户端

上文2.3节中我们创建了三个用户,但是还未对其赋予操作权限,接下来我们为其增加权限。

生产者:

bin/kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer
--authorizer-properties zookeeper.connect=localhost:2181 --add
 --allow-principal User:producer --operation Write --topic test --allow-host 192.168.2.*

消费者:

bin/kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer 
--authorizer-properties zookeeper.connect=localhost:2181 --add 
--allow-principal User:consumer--operation Read --topic test --allow-host 192.168.2.*

为生产者增加分组权限:

bin/kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer
--authorizer-properties zookeeper.connect=localhost:2181 --add 
--allow-principal User:producer --operation Read --group test-group --allow-host 192.168.2.*

分配权限之后就可以进行生产,消费操作了。(其他颗粒度的权限设置请参考官方文档)

4)查看权限

bin/kafka-acls.sh --authorizer kafka.security.auth.SimpleAclAuthorizer 
--authorizer-properties zookeeper.connect=localhost:2181 --list

2.8 小结

SASL/SCRAM验证方法可以在Kafka服务启动之后,动态的新增用户分并配权限,在业务变动频繁,开发人员多的情况下比SASL/PLAIN方法更加灵活。

3. SASL/OAUTHBEARER

SASL/OAUTHBEARER验证是Kafka2.0版中新增的验证方式:

KIP-255 adds a framework for authenticating to Kafka brokers using OAuth2 bearer tokens. The SASL/ OAuthBurer implementation is customizable using callbacks for token retrieval and validation.

KIP-255增加了一个使用OAuth2承载令牌对KafkaBroker进行认证的框架。SASL/OAuthBurer实现可使用回调进行令牌检索和验证。

3.1 Oauth2.0验证

OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本。

Oauth2.0的工作流程如下图:

kafka认证方式 java 配置 kafka用户认证_kafka_02

(A)用户打开客户端以后,客户端要求用户给予授权。

(B)用户同意给予客户端授权。

(C)客户端使用上一步获得的授权,向认证服务器申请令牌。

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

3.2 JWT规范

Oauth2.0返回验证令牌使用了JWT格式:JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户。

JWT由三个部分组成,分别是:

  • Header(头部)
  • Claims(载荷)
  • Signature(签名)

1)载荷

{
"sub": "1",
"iss": "http://localhost:8000/auth/login",
"iat": 1451888119,
"exp": 1454516119,
"jti": "37c107e4609ddbcc9c096ea5ee76c667"
"nbf": 1451888119
}

sub:该JWT所面向的用户 iss:该JWT的签发者 iat(issued at):在什么时候签发的token exp(expires):token什么时候过期 nbf(not before):token在此时间之前不能被接收处理 jti:JWT ID为web token提供唯一标识

2)头部

{
"typ": "JWT",
"alg": "HS256"
}

typ:指明数据格式 alg:指明加密算法

3)签名 以上两个部分base64编码之后链接成一个字符串,用HS256算法进行加密。在加密的时候,我们还需要提供一个密钥(secret):

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)

算出签名以后,把 Header、Payload、Signature 三个部分用"点"(.)分割拼成一个字符串,就是最后的结果。

完整JWT = 载荷 . 头部 . 签名

3.3 版本

相关包

版本

下载地址


Kafka



2.12-2.2.0



http://kafka.apache.org/downloads



Zookeeper



3.4.8



https://www.apache.org/dyn/closer.cgi/zookeeper/


Kafka2.0以上版本才支持此种验证

3.4 默认验证方式(非安全验证)

1)服务端配置:

(A)创建用于broker端通信的JAAS文件:

KafkaServer {
org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule Required
unsecuredLoginStringClaim_sub="thePrincipalName"
unsecuredLoginListClaim_scope=",KAFKA_BROKER,LOGIN_TO_KAFKA"
unsecuredValidatorRequiredScope="LOGIN_TO_KAFKA"
unsecuredValidatorAllowableClockSkewMs="3000";
};

参数说明:

选项

说明


unsecuredValidatorPrincipalClaimName="value"



默认为“sub”,如果需要修改在此定义



unsecuredValidatorScopeClaimName="value"



数值类型



unsecuredValidatorRequiredScope="value"



scope范围值,可配置字符串或者List



unsecuredValidatorAllowableClockSkewMs="value"



允许的时间偏差。单位:秒,默认0


举例:

KafkaServer {
org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required
unsecuredLoginStringClaim_sub="admin";
};

admin用户作为sub的主题用户用于kafka的broker之间通讯。

(B)在启动jvm参数中加入该文件:

-Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf

(C)配置server.properties

listeners=SASL_SSL://host.name:port (or SASL_PLAINTEXT if non-production)
security.inter.broker.protocol=SASL_SSL (or SASL_PLAINTEXT if non-production)
sasl.mechanism.inter.broker.protocol=OAUTHBEARER
sasl.enabled.mechanisms=OAUTHBEARER

2)客户端配置:

(A)配置producer.properties/consumer.properties

security.protocol=SASL_SSL (or SASL_PLAINTEXT if non-production)
sasl.mechanism=OAUTHBEARER

(B)创建客户端通信的JAAS文件(或配置文件中增加配置项):

sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required
unsecuredLoginStringClaim_sub="alice";

JAAS文件样本:

KafkaClient {
org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule Required
unsecuredLoginStringClaim_sub="thePrincipalName"
unsecuredLoginListClaim_scope="|scopeValue1|scopeValue2"
unsecuredLoginLifetimeSeconds="60";
};

参数说明:

选项

说明


unsecuredLoginStringClaim_<claimname>="value"



创建一个值为“value”的claim(不能为iat/exp)



unsecuredLoginNumberClaim_<claimname>="value"



数值类型



unsecuredLoginListClaim_<claimname>="value"



List类型



unsecuredLoginPrincipalClaimName



默认为“sub”,如果需要修改在此定义



unsecuredLoginLifetimeSeconds



超时时间单位:秒,默认3600



unsecuredLoginScopeClaimName



默认为“scope”,如果需要修改在此定义


优先级:配置文件 > JAAS文件

(C)验证过程:

在3.4中我们列出了Kafka提供的一套非安全的验证用于非正式环境,通过创建和验证JWT实现验证。只要配置对应JAAS文件即可,本节我们来看一下验证原理。

通过阅读官方文档了解到Kafka提供了一个接口,通过实现接口,创建OAuthBearer token和验证OAuthBearer token。

kafka认证方式 java 配置 kafka用户认证_Kafka_03

此类一共有两个方法,查看此接口的继承关系:

kafka认证方式 java 配置 kafka用户认证_kafka认证方式 java 配置_04

通过名字不难猜到这两个就是Kafka提供的默认的非安全的验证类

OAuthBearerUnsecuredValidatorCallbackHandler
OAuthBearerUnsecuredLoginCallbackHandler

kafka认证方式 java 配置 kafka用户认证_kafka_05

先看OAuthBearerUnsecuredLoginCallbackHandler的configure方法:在saslMechanism是OAUTHBEARER并且jaasConfigEntries存在的情况下为moduleOptions赋值。moduleOptions保存的是JAAS里面的各种配置项。

kafka认证方式 java 配置 kafka用户认证_zookeeper_06

handleCallback方法:取出配置的选项值,并组成claimsJson和headerJson,封装成OAuthBearerUnsecuredJws对象,把值赋给OAuthBearerTokenCallback。

接下来看OAuthBearerUnsecuredValidatorCallbackHandler:

kafka认证方式 java 配置 kafka用户认证_kafka认证方式 java 配置_07

kafka认证方式 java 配置 kafka用户认证_Kafka_08

在handleCallback里对callback里面的值进行校验,如果校验通过则返回OAuthBearerUnsecuredJws,验证成功,否则抛出异常。

3.5 安全验证

Kafka官方文档中说明:

Production use cases will require writing an implementation of org.apache.kafka.common.security.auth.AuthenticateCallbackHandler that can handle an instance of org.apache.kafka.common.security.oauthbearer.OAuthBearerTokenCallback and declaring it via either the sasl.login.callback.handler.class configuration option for a non-broker client or via the listener.name.sasl_ssl.oauthbearer.sasl.login.callback.handler.class configuration option for brokers (when SASL/OAUTHBEARER is the inter-broker protocol). Production use cases will also require writing an implementation of org.apache.kafka.common.security.auth.AuthenticateCallbackHandler that can handle an instance of org.apache.kafka.common.security.oauthbearer.OAuthBearerValidatorCallback and declaring it via the listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class broker configuration option.

分别需要编写两个实现类处理OAuthBearerTokenCallback并分别在:

listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
listener.name.sasl_ssl.oauthbearer.sasl.login.callback.handler.class或者sasl.login.callback.handler.class

3.6 配置

上一节我们讨论了Kafka默认提供的两个实现类,分别实现了AuthenticateCallbackHandler接口,并验证了基于JWT格式的token。受此启发我们可以编写自己的实现类。

1)服务端配置

(A)创建JAAS文件:

KafkaServer {
org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required
LoginStringClaim_sub="admin";
};

(B)在启动jvm参数中加入该文件:

-Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf

(C)配置server.properties:

listeners=SASL_SSL://host.name:port (or SASL_PLAINTEXT if non-production)
security.inter.broker.protocol=SASL_SSL (or SASL_PLAINTEXT if non-production)
sasl.mechanism.inter.broker.protocol=OAUTHBEARER
sasl.enabled.mechanisms=OAUTHBEARER

2)实现接口:此处只给出思路,具体验证过程根据业务需求定制,我们定义两个类:

@Override
</span><span >public</span> <span >void</span> handle(Callback[] callbacks) <span >throws</span><span > IOException, UnsupportedCallbackException {
    </span><span >if</span> (!<span >isConfigured())
        </span><span >throw</span> <span >new</span> IllegalStateException("Callback handler not configured"<span >);
    </span><span >for</span><span > (Callback callback : callbacks) {
        </span><span >if</span> (callback <span >instanceof</span><span > OAuthBearerValidatorCallback)
            </span><span >try</span><span > {
                OAuthBearerValidatorCallback validationCallback </span>=<span > (OAuthBearerValidatorCallback) callback;
                handleCallback(validationCallback);
            } </span><span >catch</span><span > (KafkaException e) {
                </span><span >throw</span> <span >new</span><span > IOException(e.getMessage(), e);
            }
        </span><span >else</span>
            <span >throw</span> <span >new</span><span > UnsupportedCallbackException(callback);
    }
}

</span><span >private</span> <span >void</span><span > handleCallback(OAuthBearerValidatorCallback callback) {
    String accessToken </span>=<span > callback.tokenValue();
    </span><span >if</span> (accessToken == <span >null</span><span >)
        </span><span >throw</span> <span >new</span> IllegalArgumentException("Callback missing required token value"<span >);

    log.info(</span>"Trying to introspect Token!"<span >);
    OauthBearerTokenJwt token </span>=<span > OauthHttpClient.introspectBearer(accessToken);
    log.info(</span>"Trying to introspected"<span >);

    </span><span >//</span><span > Implement Check Expire Token..</span>
    <span >long</span> now =<span > time.milliseconds();
    </span><span >if</span> (now ><span > token.expirationTime()) {
        OAuthBearerValidationResult.newFailure(</span>"Expired Token, needs refresh!"<span >);
    }

    log.info(</span>"Validated! token.."<span >);
    callback.token(token);
}
@Override
</span><span >public</span> <span >void</span> handle(Callback[] callbacks) <span >throws</span><span > IOException, UnsupportedCallbackException {
    </span><span >if</span> (!<span >isConfigured())
        </span><span >throw</span> <span >new</span> IllegalStateException("Callback handler not configured"<span >);
    </span><span >for</span><span > (Callback callback : callbacks) {
        </span><span >if</span> (callback <span >instanceof</span><span > OAuthBearerTokenCallback)
            </span><span >try</span><span > {
                handleCallback((OAuthBearerTokenCallback) callback);
            } </span><span >catch</span><span > (KafkaException e) {
                </span><span >throw</span> <span >new</span><span > IOException(e.getMessage(), e);
            }
        </span><span >else</span>
            <span >throw</span> <span >new</span><span > UnsupportedCallbackException(callback);
    }
}

</span><span >private</span> <span >void</span><span > handleCallback(OAuthBearerTokenCallback callback) {
    </span><span >if</span> (callback.token() != <span >null</span><span >)
        </span><span >throw</span> <span >new</span> IllegalArgumentException("Callback had a toke" +
                "n already"<span >);

    log.info(</span>"Try to acquire token!"<span >);
    OauthBearerTokenJwt token </span>= OauthHttpClient.login(<span >null</span><span >);
    log.info(</span>"Retrieved token.."<span >);
    </span><span >if</span> (token == <span >null</span><span >) {
        </span><span >throw</span> <span >new</span> IllegalArgumentException("Null token returned from server"<span >);
    }
    callback.token(token);
}

区别在于这两个方法:

  • login方法主要是客户端用自己的信息(可是是用户名/密码或者token)创建http或者https请求去Oauth服务器申请token,并封装OauthBearerTokenJwt返回。
  • introspectBearer方法利用自己的accessToken去Oauth服务器做验证(查询数据库,验证失效时间等等),验证成功后同样返回OauthBearerTokenJwt。

本人用springboot搭建一个简易的后端用来模拟Oauth服务。

小结

本节介绍了自Kafka2.0版本新增的SASL/OAUTHBEARER验证以及相关Oauth和JWT技术。分别介绍了Kafka默认的非安全验证方法和正式环境的验证实现方法。

SASL/OAUTHBEARER可以加密传输验证信息,自定义实现类处理创建/验证token。在此过程中可以对接数据库,便于持久化用户权限信息。