go中使用SSH认证连接MongoDB

一、说明

go连接MongoDB驱动库mongo-drivermgo.v2库中都不支持ssh认证连接的。但是我们可以使用net库先与MongoDB数据库服务器建立ssh连接,然后再将MongoDB数据库所在服务器端口映射到本地连接中转发就可以了。

二、使用

下面以mongo-driver数据库驱动为例。

安装

go get -u github.com/zngw/sshtunnel

实现代码

// @Title 
// @Description $
// @Author  55
// @Date  2021/11/7
package main

import (
    "context"
    "github.com/zngw/log"
    "github.com/zngw/sshtunnel/ssht"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/mongo/readpref"
    "net/url"
    "strings"
    "time"
)

func main() {
    sshUri := "ssh://root:123456@192.168.1.55:22"
    mdbUri := "mongodb://root:123456@127.0.0.1:27017/admin"

    u, err := url.Parse(mdbUri)
    if err != nil {
        log.Error("test", "解析数据库连接信息失败 %v", err)
        return
    }

    listen, err := ssht.TunnelUri(sshUri, u.Host, ":3717")
    if err != nil {
        log.Error("test", "启用ssh端口映射失败 %v", err)
    } else {
        log.Info("test", "启用ssh端口映射成功 %s", listen)
    }

    // 替换数据库地址端口
    mdbUri = strings.Replace(mdbUri, u.Host, listen, -1)

    // 下面按正常逻辑连接mongodb
    name := "Test"
    maxTime := time.Duration(2)     // 链接超时时间
    table := "test"                 // 表名

    // 连接数据库
    db, err := ConnectToDB(mdbUri, name, maxTime)
    if err != nil {
        log.Error("test","链接数据库有误!")
    }

    // 获取test表数据数量
    collection := db.Collection(table)
    count, err := collection.CountDocuments(context.Background(), bson.D{})
    if err != nil {
        log.Error("test", err.Error())
        return
    }

    log.Info("test","collection.CountDocuments: %v", count)
}

func ConnectToDB(uri, name string, timeout time.Duration) (*mongo.Database, error)  {
    // 设置连接超时时间
    ctx, cancel := context.WithTimeout(context.Background(), timeout)
    defer cancel()
    // 通过传进来的uri连接相关的配置
    o := options.Client().ApplyURI(uri)
    // 发起链接
    client, err := mongo.Connect(ctx, o)
    if err != nil {
        log.Error("test",err.Error())
        return nil, err
    }
    // 判断服务是不是可用
    if err = client.Ping(context.Background(), readpref.Primary()); err != nil {
        log.Error("test",err.Error())
        return nil, err
    }
    // 返回 client
    return client.Database(name), nil
}
0%