pulsar自定义认证插件开发

pulsar自定义认证插件开发

pulsar的权限分为两部分:

  • 1 客户端连接时认证的权限

  • 2 客户端发送和订阅主题的权限

pulsar开启认证功能

默认情况下,pulsar是不会开启客户端连接认证的,即客户端到broker之间、broker到broker之间的访问都没有任何限制。但是在线上环境中,对于权限的控制往往是很重要的。

修改配置,开启认证功能
standalone.conf 或 broker.conf

#开启认证
authenticationEnabled=true

#认证处理类: 可以提供N个处理认证的处理类,逗号分隔, 然后broker接收到客户端连接后就会调用此类的方法进行处理
authenticationProviders=com.beyond.auth.AuthenticationProviderMysql

# 这里是broker与broker之间连接时的认证,broker客户端用到的处理类。通常可以和客户端的认证处理类一样。
# 正式项目中,需要在broker端判断是哪一种连接,分别做好权限认证。
# broker与broker之间认证最好使用admin权限,它们之前可能需要同步数据等
brokerClientAuthenticationPlugin=com.beyond.auth.AuthenticationMysql
brokerClientAuthenticationParameters=e3592948c:admin:123456

#配置超级权限
superUserRoles=admin

自定义认证插件开发

pulsar提供了Authentication接口。为我们自定义认证实现接口

认证分为客户端和服务端,服务端即broker,客户端即我们自己编写的producer或者consumer。
服务端需要实现org.apache.pulsar.broker.authentication.AuthenticationProvider接口,客户端需要实现org.apache.pulsar.client.api.Authentication。

下面分别给出服务端和客户端的代码。

服务端认证代码

package com.beyond.auth;

import org.apache.pulsar.broker.ServiceConfiguration;
import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
import org.apache.pulsar.broker.authentication.AuthenticationProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.naming.AuthenticationException;
import java.io.IOException;
import java.util.Set;

public class AuthenticationProviderMysql implements AuthenticationProvider {
    
    

    private static final Logger log = LoggerFactory.getLogger(AuthenticationProviderMysql.class);

    private static final String methodName = "mysql";

    private String header = "auth";

    @Override
    public void initialize(ServiceConfiguration config) throws IOException {
    
    
        log.info("initialize##################" + methodName + "####################");
        if (config == null) {
    
    
            return;
        }

        Set<String> superRoles = config.getSuperUserRoles();
        if (superRoles == null) {
    
    
            return;
        }
        for (String role : superRoles) {
    
    
            log.info("initialize##################" + methodName + "#####222222#######" + role);
        }
    }

    @Override
    public String getAuthMethodName() {
    
    
        log.info("getAuthMethodName##################" + methodName + "################");
        return methodName;
    }

    @Override
    public String authenticate(AuthenticationDataSource authData) throws AuthenticationException {
    
    
        log.info("authenticate##################" + methodName + "#################");

        String roleToken = "unknown";
        if (authData.hasDataFromCommand()) {
    
    
            roleToken = authData.getCommandData();
        } else if (authData.hasDataFromHttp()) {
    
    
            roleToken = authData.getHttpHeader(header);
        } else {
    
    
            throw new AuthenticationException("Authentication data source does not have a role token############");
        }

        log.info("authenticate##################" + methodName + "####3333############" + roleToken);
	
	//查询数据库,或调用接口,判断roleToken的正确性,并返回role
        //String aaa = MysqlConfig.queryToken("select bbb from test where aaa = ? ", token);
        System.out.println("====##################======mysql==" + aaa);
        return aaa;
    }

    @Override
    public void close() {
    
    
        log.info("close##################" + methodName + "##############");
    }
}


客户端连接认证代码

package com.beyond.auth;

import org.apache.pulsar.client.api.Authentication;
import org.apache.pulsar.client.api.AuthenticationDataProvider;
import org.apache.pulsar.client.api.EncodedAuthenticationParameterSupport;
import org.apache.pulsar.client.api.PulsarClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;

public class AuthenticationMysql implements Authentication, EncodedAuthenticationParameterSupport {
    
    

    private static final Logger log = LoggerFactory.getLogger(AuthenticationMysql.class);

    private static final String methodName = "mysql";

    @Override
    public String getAuthMethodName() {
    
    
        log.info("getAuthMethodName $$$$$$$$$" + methodName + "$$$$$$$$$$$$$$");
        return methodName;
    }

    @Override
    public AuthenticationDataProvider getAuthData() throws PulsarClientException {
    
    
        log.info("getAuthData $$$$$$$$$" + methodName + "$$$$$$$$$$$$$");
        return new AuthenticationDataMysql();
    }

    @Override
    public void configure(String encodedAuthParamString) {
    
    
        log.info("configure $$$$$$$$$" + methodName + "@@@@@@@@" + encodedAuthParamString);
    }

    @Override
    public void configure(Map<String, String> authParams) {
    
    
    }

    @Override
    public void start() throws PulsarClientException {
    
    
        log.info("start $$$$$$$$$" + methodName + "@@@@@@@");
    }

    @Override
    public void close() throws IOException {
    
    
        log.info("close $$$$$$$$$" + methodName + "@@@@@@");
    }
}

package com.beyond.auth;

import org.apache.pulsar.client.api.AuthenticationDataProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class AuthenticationDataMysql implements AuthenticationDataProvider {
    
    

    private static final Logger log = LoggerFactory.getLogger(AuthenticationDataMysql.class);

    private static final String methodName = "mysql";

    private String header = "auth";

    private String token = "liang";

    @Override
    public boolean hasDataForHttp() {
    
    
        log.info("hasDataForHttp@@@@@@@@" + methodName + "@@@@@@@@@@@@@@");
        return true;
    }

    @Override
    public Set<Map.Entry<String, String>> getHttpHeaders() throws Exception {
    
    
        log.info("getHttpHeaders@@@@@@@@" + methodName + "@@@@@@@");
        Map<String, String> headers = new HashMap<>();
        headers.put(header, token);
        return headers.entrySet();

    }

    @Override
    public boolean hasDataFromCommand() {
    
    
        log.info("hasDataFromCommand@@@@@@@@" + methodName + "@@@@@@@@@@");
        return true;
    }

    @Override
    public String getCommandData() {
    
    
        log.info("getCommandData@@@@@@@@" +  methodName + "@@@@@@@@@" + token);
        return token;
    }
}

打包部署

编写好代码后用maven命令打包:
mvn clean install -Dmaven.test.skip=true

然后把打好的jar包放到pulsar的lib目录下,如:apache-pulsar-2.8.1/lib,
重启broker组件即可生效。

测试自定义认证功能

maven引入pulsar-client依赖

        <dependency>
            <groupId>org.apache.pulsar</groupId>
            <artifactId>pulsar-client</artifactId>
            <version>2.8.0</version>
        </dependency>
package com.beyond.auth;

import org.apache.pulsar.client.api.*;

public class TestPulsar {
    
    

    public static void main(String[] args) throws Exception {
    
    

        PulsarClient client = PulsarClient.builder()
                .serviceUrl("pulsar://127.0.0.1:6650")
                .authentication("com.beyond.auth.AuthenticationMysql", "e3592948c:admin:123456")
                .build();

        //订阅
        ConsumerThread consumerThread = new ConsumerThread(client);
        consumerThread.start();

        //发布
        Producer<String> stringProducer = client.newProducer(Schema.STRING)
                .topic("persistent://my-tenant/my-namespace/aaa")
                .create();
        for (int i = 0; i < 100; i++) {
    
    
            Thread.sleep(1000);
            stringProducer.send(i + "aaaaaaaa111112222333");
        }


    }

}

class ConsumerThread extends Thread {
    
    

    private PulsarClient client;

    public ConsumerThread(PulsarClient client) throws Exception {
    
    
        this.client = client;
    }

    @Override
    public void run()  {
    
    
        try {
    
    
            Consumer consumer = client.newConsumer()
                    .topicsPattern("persistent://my-tenant/my-namespace/aaa")
                    .subscriptionName("my-subscription")
                    .subscriptionType(SubscriptionType.Shared)
                    .subscribe();


            while (true) {
    
    
                // Wait for a message
                Message msg = consumer.receive();

                try {
    
    
                    // Do something with the message
                    System.out.println(msg.getTopicName() + "222222Message received: " + new String(msg.getData()));

                    // Acknowledge the message so that it can be deleted by the message broker
                    consumer.acknowledge(msg);
                } catch (Exception e) {
    
    
                    // Message failed to process, redeliver later
                    consumer.negativeAcknowledge(msg);
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

    }
}

参考链接:
https://blog.csdn.net/casuallc/article/details/119151573

猜你喜欢

转载自blog.csdn.net/yinjl123456/article/details/121057596
今日推荐