最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

分布式数据库中间件–(2)Cobar与客户端的握手认证

来源:懂视网 责编:小采 时间:2020-11-09 12:56:23
文档

分布式数据库中间件–(2)Cobar与客户端的握手认证

分布式数据库中间件–(2)Cobar与客户端的握手认证:Cobar启动完成,监听特定端口。整个认证的流程图: NIOAcceptor类继承自Thread类,该类的对象会以线程的方式运行,进行连接的监听。NIOAcceptor启动的初始化过程如下:1 、打开一个selector,获取一个ServerSocketChannel对象,对该对象的so
推荐度:
导读分布式数据库中间件–(2)Cobar与客户端的握手认证:Cobar启动完成,监听特定端口。整个认证的流程图: NIOAcceptor类继承自Thread类,该类的对象会以线程的方式运行,进行连接的监听。NIOAcceptor启动的初始化过程如下:1 、打开一个selector,获取一个ServerSocketChannel对象,对该对象的so
注意最后一个this指针参数,表示将该连接作为附件,注册到selector,当有感兴趣的时间发生时,函数selector.selectedKeys()返回的SelectionKey集合中的对象中使用key.attachment()即可获取到上面注册时绑定的connection对象指针附件。目的就是为了通过该附件对象调用该连接类中定义的read函数来完成功能。如下所示:
 private void read(NIOConnection c) {
 try {
 c.read();
 } catch (Throwable e) {
 c.error(ErrorCode.ERR_READ, e);
 }
 }
6、 连接类中定义的read函数定义在AbstractConnection类中。在该read函数(该read函数涉及到的逻辑比较复杂,先不深究)中,完成从channel中读取数据到buffer,然后从buffer中提取byte数据交给具体子类(FrontendConnection)的handle()方法进行处理。 7、 该方法会从processor的线程池中获取一个线程,来异步执行数据的处理。处理会调用成员handler的handle方法来对数据进行处理。这里,在FrontendConnection的构造函数中定handler设置为FrontendAuthenticator(进行前端认证)。
 public void handle(final byte[] data) {
 // 从线程池获取一个线程,异步处理前端数据
 	// 从processor中的线程池中获取一个可以执行的线程,执行Runnable任务
 processor.getHandler().execute(new Runnable() {
 @Override
 public void run() {
 try {
 //调用具体NIOHandler子类的handle函数
 handler.handle(data);
 } catch (Throwable t) {
 error(ErrorCode.ERR_HANDLE_DATA, t);
 }
 }
 });
 }
8、 handler在构造函数中初始化成前端认证处理器,用于处理前端权限认证。
 public FrontendConnection(SocketChannel channel) {
 super(channel);
 .....................
 //前端认证处理器
 this.handler = new FrontendAuthenticator(this);
 }
9、 由于Cobar是基于MySQL协议的,所以需要分析一下MySQL协议的具体格式。下面就先分析一下MySQL认证数据包的格式: 每个报文都分为消息头和消息体两部分,其中消息头是固定的四个字节,报文结构如下: mysql_protocol_struct 登录认证报文的报文数据部分格式如下: mysql_protocol_auth_41 10、 FrontendAuthenticator类对上面的数据包的具体处理如下:
  • 读取信息到认证包对象
  • 核对用户
  • 核对密码
  • 检查schema
  • 如果出现错误,会提示相应的错误信息,如果正确会向客户端发送认证成功提示。
     public void handle(byte[] data) {
     // check quit packet
     if (data.length == QuitPacket.QUIT.length && data[4] == MySQLPacket.COM_QUIT) {
     source.close();
     return;
     }
     //新建认证包对象
     AuthPacket auth = new AuthPacket();
     //读取认证包到对象
     auth.read(data);
     // check user
     if (!checkUser(auth.user, source.getHost())) {
     failure(ErrorCode.ER_ACCESS_DENIED_ERROR, "Access denied for user '" + auth.user + "'");
     return;
     }
     // check password
     if (!checkPassword(auth.password, auth.user)) {
     failure(ErrorCode.ER_ACCESS_DENIED_ERROR, "Access denied for user '" + auth.user + "'");
     return;
     }
     // check schema
     switch (checkSchema(auth.database, auth.user)) {
     case ErrorCode.ER_BAD_DB_ERROR:
     failure(ErrorCode.ER_BAD_DB_ERROR, "Unknown database '" + auth.database + "'");
     break;
     case ErrorCode.ER_DBACCESS_DENIED_ERROR:
     String s = "Access denied for user '" + auth.user + "' to database '" + auth.database + "'";
     failure(ErrorCode.ER_DBACCESS_DENIED_ERROR, s);
     break;
     default:
     //认证成功,向客户端发送认证结果消息
     success(auth);
     }
     }
    在上面的auth.read函数中会按9中的协议格式进行读取数据到auth对象。认证成功后会执行:
     protected void success(AuthPacket auth) {
     	//认证通过,设置连接属性:已认证\用户\数据库\处理器
     source.setAuthenticated(true);
     source.setUser(auth.user);
     source.setSchema(auth.database);
     source.setCharsetIndex(auth.charsetIndex);
     //设置该连接的连接处理器为前端命令处理器
     source.setHandler(new FrontendCommandHandler(source));
     .......
     ByteBuffer buffer = source.allocate();
     source.write(source.writeToBuffer(AUTH_OK, buffer));
     }
    可以看到,在上面的函数中,设置连接对象source中的成员(是否认证、用户、数据库、编码、处理该连接后续数据包的处理器【handle方法】) 然后回复认证成功的消息。后面客户端再发送消息,会交给前端命令处理器进行处理。 客户端进行链接的时候Cobar服务器的输出:
    16:59:19,388 INFO ===============================================
    16:59:19,389 INFO Cobar is ready to startup ...
    16:59:19,389 INFO Startup processors ...
    16:59:19,455 INFO Startup connector ...
    16:59:19,460 INFO Initialize dataNodes ...
    16:59:19,506 INFO dnTest1:0 init success
    16:59:19,514 INFO dnTest3:0 init success
    16:59:19,517 INFO dnTest2:0 init success
    16:59:19,527 INFO CobarServer is started and listening on 8066
    16:59:19,527 INFO ===============================================
    16:59:23,459 DEBUG 1>>NIOReactor接受连接数:0
    16:59:23,464 DEBUG 2>>NIOReactor接受连接数:1
    16:59:23,465 DEBUG select读事件
    16:59:23,465 INFO com.alibaba.cobar.net.handler.FrontendAuthenticator接收的请求长度:62
    58 0 0 1 5 166 15 0 0 0 0 1 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 114 111 111 116 0 20 169 171 247 102 133 96 158 224 121 22 226 229 88 244 119 238 185 61 124 219 
    16:59:23,468 INFO [thread=Processor1-H0,class=ServerConnection,host=192.168.137.8,port=46101,schema=null]'root' login success
    客户端得到的回复:
    yan@yan-Z400:~$ mysql -uroot -p** -P8066 -h192.168.137.8
    Welcome to the MySQL monitor. Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 5.1.48-cobar-1.2.7 Cobar Server (ALIBABA)
    Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    mysql>
    MySQL客户端的命令处理,具体后续会分析。

    文档

    分布式数据库中间件–(2)Cobar与客户端的握手认证

    分布式数据库中间件–(2)Cobar与客户端的握手认证:Cobar启动完成,监听特定端口。整个认证的流程图: NIOAcceptor类继承自Thread类,该类的对象会以线程的方式运行,进行连接的监听。NIOAcceptor启动的初始化过程如下:1 、打开一个selector,获取一个ServerSocketChannel对象,对该对象的so
    推荐度:
    标签: 握手 认证 客户端
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top