GVKun编程网logo

如何在pymongo连接中的密码中转义@?(python密码密文转换)

13

如果您对如何在pymongo连接中的密码中转义@?感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于如何在pymongo连接中的密码中转义@?的详细内容,我们还将为您解答pyt

如果您对如何在pymongo连接中的密码中转义@?感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于如何在pymongo连接中的密码中转义@?的详细内容,我们还将为您解答python密码密文转换的相关问题,并且为您提供关于(原创) 使用 pymongo 3.6.0 连接 MongoDB 的正确姿势、bash – 如何在smb:// URL的密码字段中转义@符号、golang使用mgo连接MongoDB、Mongodb-- python中使用pymongo连接mongodb数据库的有价值信息。

本文目录一览:

如何在pymongo连接中的密码中转义@?(python密码密文转换)

如何在pymongo连接中的密码中转义@?(python密码密文转换)

我的问题是我如何通过pymongo验证mongodb身份验证的用户名密码的规范?。

我正在尝试使用PyMongo 3.2.2和包含用户名和密码的URL连接到MongoDB实例,如MongoDB
Docs中所述
。所不同的是,我使用的密码包含一个“ @”。

刚开始,我只是尝试不逃避地连接,就像这样:

前缀=’mongodb://’

用户=’用户:passw_with _ @ _’

后缀=’@ 127.0.0.1:27001 /’

conn = pymongo.MongoClient(前缀+用户+后缀)

自然地,我得到以下错误:

InvalidURI: ':' or '@' characters in a username or password must be escaped according to RFC 2396.

所以我尝试使用urllib.quote()来转义user:pass部分,如下所示:

前缀=’mongodb://’

用户= urllib.quote(’user:passw_with _ @ _’)

后缀=’@ 127.0.0.1:27001 /’

conn = pymongo.MongoClient(前缀+用户+后缀)

但后来我得到了:

OperationFailure: Authentication failed.

(重要的是,使用GUI
MongoDB管理工具(Robomongo,如果重要的话),我可以使用(真实)地址和凭据连接到MongoDB。)

在上面的代码中打印用户变量会生成一个'user:passw_with_%40_'字符串(即’@’变为’%40’),并且根据Wikipedia的预期,这是可以避免的。

我什至尝试使用单反斜杠(user = 'user:passw_with_\\@_'user = 'user:passw_with_\@_')来转义@ ,但是由于InvalidURI异常而失败。

TL; DR;

我的问题是:如何在MongoDB URL的密码部分中转义“ @”?

(原创) 使用 pymongo 3.6.0 连接 MongoDB 的正确姿势

(原创) 使用 pymongo 3.6.0 连接 MongoDB 的正确姿势

0. 疑惑

前两天使用 pymongo 连接 MongoDB 的时候发现了一个奇怪的现象:我本机 MongoDB 并没有打开,但是使用 pymong.MongoClient () 进行连接时,并没有异常,我的服务端也正常跑起来了,直到收到请求,进行数据库查询操作的时候,等了相当长的一段时间之后,服务端才由于 MongoDB 连接不上报异常。

  Note: 本机环境pymongo 3.6.0MongoDB 3.4.6 

不信?可以打开 ipython,输入如下命令:

from pymongo import MongoClient
client = MongoClient(''aaa'', 1234)
db = client.database
task = db.task

怎么样?是不是一直 ok
再执行下面这条命令呢?

task.count()

等待相当长的一段时候后报错了:

ServerSelectionTimeoutError: aaa:1234: [Errno 11001] getaddrinfo failed 

如图 1 所示


 
图 1

1. 解答

那这是为什么呢?
按一般的理解,MongoClient 接口实现的时候肯定要考虑 MongoDB 连接异常的情况,只有确保连接成功建立,才能一步一步往下取 database、取 collection、基于 collection 进行增删改查操作等等。
这里为什么不呢 ?我发现了一个大 BUG?不应该啊,pymongo 发布使用的时间比我用 Python 写代码都要长,这要是 bug 早该解决了。
如何使用 pymongo 连接 MongoDB,网上确实有很多很多博客,不过绝大多数都很简单,基本就我上面那几行的正确使用而已,顶多再提醒一下安装 pymongo 的时候不能安装第三方 bson,因为 pymongo 自带 bson,两者不匹配,讲如何进行密码验证的都很少,更别说 replSet 参数的使用。
终于还是在官网的 API 接口文档中 MongoClient 的解释中找到了答案:

 
图 2

简单翻译一下:
从 pymongo3.0 版本开始,MongoClient 的构造函数就不会再阻塞等待 MongoDB 连接的建立,即使连接不上也不会上报 ConnectionFailure,用户提交的资格证书(估计是用户名密码或者 cert 证书)是错误的也不会上报 ConfigurationError。相反,构造函数会立即返回并在后台线程中加载处理连接数据的进程。如果想确认返回的 client 是否真实可用,可以如下操作:

 

# The ismaster command is cheap and does not require auth.
    client.admin.command(''ismaster'')

这说明至少 3.0 之前版本的设计和我的想法是一样的,那现在为什么换了高级玩法呢?还是不太明白

至于为什么执行命令时上报异常的时间比较长呢?


 
图 3

图 3 和图 1 中的时间差达到了近 40s
因为两个参数:
connectTimeoutMS,连接 mongo 的超时机制, 默认 20s
serverSelectionTimeoutMS,连接 database 的超时机制, 默认 30s

虽然上面说过 MongoClient 的构造函数不再阻塞建立连接,但那个 note 上面还有一句话:

Note:  MongoClient creation will block waiting for answers from DNS when mongodb+srv:// URIs are used.

当使用 "mongodb+srv://"形式的 URI 连接数据库服务器时,MongoClient 将会阻塞等到 DNS 的域名解析结果,但同样不是数据库的连接。估计这种"mongodb+srv://" 形式的 URI 是用来连接 MongoDB 去年提出的云服务吧,要不哪来的 DNS 解析需求呢。

2. 更新汇总

简单说一下 MongoClient 中提到的一些更新要点:

  • 版本 3.6:新增 mongodb+srv:// 形式的 URI,新增 retryWrites 关键字变量和 URI 选项
  • 版本 3.5: 新增 ''username'' 和 ''password'' 两个选项。新增 ''authSource''、''authMechanism''、''authMechanismProperties'' 三个选项的文档。舍弃''socketKeepAlive'' 关键字变量和 URI 选项。 socketKeepAlive 默认值改为 True。
  • 版本 3.0:"pymongo.mongo_client.MongoClient" 现在是唯一的 client 类,应用于独立的 Mongo 服务器、多台 Mongos、Mongo 集群。它兼容了 “MongoReplicaSetClient” 的功能,可以连接 Mongo 集群、寻找集群成员等操作,后者已被弃用。
  • MongoClient 的构造函数就不会再阻塞等待 MongoDB 连接的建立,即使连接不上也不会上报 ConnectionFailure,用户提交的资格证书(估计是用户名密码或者 cert 证书)是错误的也不会上报 ConfigurationError。相反,构造函数会立即返回并在后台线程中加载处理连接数据的进程。
  • 因此 “alive” 方法也弃用了,因为它不再能提供有效信息;如果服务器连接断开了,在执行下一次操作的时候异常就会被发现。
  • 在 Pymongo 2.x 中,MongoClient 可以接受单例数据库的地址列表做参数,并自动连接第一个可用的数据库。
MongoClient([''host1.com:27017'', ''host2.com:27017''])

不再支持多服务器的地址列表,如果要给列表的话,这些服务器一定要配置在同一个集群中。

  • 在 mongo 集群中行为不再讲究 “高可用”,而是 “负载均衡”。因为以前只是在连的时候优先连接最低负载的服务器,除非网络异常才会连别的,但实际上这个 “最低” 可能只是一时的。而在 Pymongo 3.x 中,改为统一监控集群网络实时负载了。
  • 新增 “connect” URI 选项(True 立即连接,false 第一个操作时才连接)
connect参数我试过并没有作用,或许在3.6版本中一并失效了吧
  • “start_request”、“in_request”、“end_request ” 三个方法和 “auto_start_request ” 选项都被移除了。
  • “copy_database” 方法被移除了
  • MongoClient.disconnect () 被移除了,它和 close () 一样的。
  • MongoClient 不再支持以实例属性方式读取下划线开头命名的数据库属性了,必须以字典形式读取。
YES: client[''__my_database__''],  NO: client.__my_database__ 

3. 总结

  • 1)两种基本的连接方法,一种是使用 keyword argument(关键字变量),另一种是 MongoDB URI format(URI 参数)
from pymongo import MongoClient
client = MongoClient()
# keyword argument
client = MongoClient(''localhost'', 27017) # MongoDB URI client = MongoClient(''mongodb://localhost:27017/'') 
  • 2)用户名密码验证
    note: MongoDB 3.0(对应 pymongo2.8)之后默认使用 “SCRAM-SHA-1” 加解密;之前使用的是 “MONGODB-CR”,可以使用 authMechanism 指定;同时可以使用 authSource 指定应用加解密的 database,默认是 admin。
# since MongoDB 3.0, SCRAM-SHA-1
from pymongo import MongoClient
# keyword argument
client = MongoClient(''example.com'', username=''user'', password=''password'', authSource=''the_database'', authMechanism=''SCRAM-SHA-1'') # MongoDB URI uri = "mongodb://user:password@example.com/the_database?authMechanism=SCRAM-SHA-1" client = MongoClient(uri) 
  • 3)replSet
    假设本地有如下的集群配置
config = {''_id'': ''foo'', ''members'': [
     {''_id'': 0, ''host'': ''localhost:27017''}, {''_id'': 1, ''host'': ''localhost:27018''}, {''_id'': 2, ''host'': ''localhost:27019''}]} 

可以通过 replSet 参数指定集群名称(_id),主库、从库等都可以读取到,这里就不细说了

>>> MongoClient(''localhost'', replicaset=''foo'')
MongoClient(host=[''localhost:27017''], replicaset=''foo'', ...) >>> MongoClient(''localhost:27018'', replicaset=''foo'') MongoClient([''localhost:27018''], replicaset=''foo'', ...) >>> MongoClient(''localhost'', 27019, replicaset=''foo'') MongoClient([''localhost:27019''], replicaset=''foo'', ...) >>> MongoClient(''mongodb://localhost:27017,localhost:27018/?replicaSet=foo'') MongoClient([''localhost:27017'', ''localhost:27018''], replicaset=''foo'', ...) 
    1. "mongodb+srv://"
      这种形式的 URL 只支持一个 hostname,对应 DNS server,进行 SRV record 查询,它也支持 replSet 和 authSource(TXT record),需要注意的是它默认使用 TLS,即 ssl=True。
      具体的说明还是看 initial-dns-seedlist-discovery
      假设我们使用
mongodb+srv://server.mongodb.com/

而 DNS server(_mongodb._tcp.server.mongodb.com)上有如下 SRV record

Record                            TTL   Class    Priority Weight Port Target _mongodb._tcp.server.mongodb.com. 86400 IN SRV 0 5 27317 mongodb1.mongodb.com. _mongodb._tcp.server.mongodb.com. 86400 IN SRV 0 5 27017 mongodb2.mongodb.com. 

且 server.mongdb.com 存在如下 Txt records

Record              TTL   Class    Text
server.mongodb.com. 86400 IN TXT   "replicaSet=replProduction&authSource=authDB"

那么对应解析结果就是:

mongodb://mongodb1.mongodb.com:27317,mongodb2.mongodb.com:27107/?ssl=true&replicaSet=replProduction&authSource=authDB
    1. SSL
      一堆的参数,还没有用过,自行看文档吧。

4. 代码示例

此处给出一份使用 pymongo3.6 连接 MongoDB 的代码示例,分别是 OPTION 和 URI 两种方式
主要考虑集群配置和密码校验两个方面,假设配置文件如下

MONGODB = {
    ''host'': ''127.0.0.1'',
    ''port'': ''27017'',
    ''user'': '''', ''pwd'': '''', ''db'': ''test'', ''replicaSet'': { ''name'': ''abc'', "members": [ { "host": "localhost", "port": "27017" }, { "host": "localhost", "port": "27027" }, { "host": "localhost", "port": "27037" } ] } } 

约定如下:

replicaSet的name为空则不使用集群配置
user和pwd为空则不需要进行密码校验
db不给出则默认为“admin”

则 OPTION 方式:

import urllib.parse

import pymongo

from config import MONGODB

if MONGODB[''replicaSet''][''name'']: host_opt = [] for m in MONGODB[''replicaSet''][''members'']: host_opt.append(''%s:%s'' % (m[''host''], m[''port''])) replicaSet = MONGODB[''replicaSet''][''name''] else: host_opt = ''%s:%s'' % (MONGODB[''host''], MONGODB[''port'']) replicaSet = None option = { ''host'': host_opt, ''authSource'': MONGODB[''db''] or ''admin'', # 指定db,默认为''admin'' ''replicaSet'': replicaSet, } if MONGODB[''user''] and MONGODB[''pwd'']: # py2中为urllib.quote_plus option[''username''] = urllib.parse.quote_plus(MONGODB[''user'']) option[''password''] = urllib.parse.quote_plus(MONGODB[''pwd'']) option[''authMechanism''] = ''SCRAM-SHA-1'' client = pymongo.MongoClient(**option) 

URI 方式

import urllib.parse

import pymongo

from config import MONGODB

# mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] params = [] host_info = '''' # 处理replicaSet设置 if MONGODB[''replicaSet''][''name'']: host_opt = [] for m in MONGODB[''replicaSet''][''members'']: host_opt.append(''%s:%s'' % (m[''host''], m[''port''])) host_info = ('','').join(host_opt) replicaSet_str = ''replicaSet=%s'' % MONGODB[''replicaSet''][''name''] params.append(replicaSet_str) else: host_info = ''%s:%s'' % (MONGODB[''host''], MONGODB[''port'']) # 处理密码校验 if MONGODB[''user''] and MONGODB[''pwd'']: # py2中为urllib.quote_plus username = urllib.parse.quote_plus(MONGODB[''user'']) password = urllib.parse.quote_plus(MONGODB[''pwd'']) auth_str = ''%s:%s@'' % (username, password) params.append(''authMechanism=SCRAM-SHA-1'') else: auth_str = '''' if params: param_str = ''?'' + ''&''.join(params) else: param_str = '''' uri = ''mongodb://%s%s/%s%s'' % (auth_str, host_info, MONGODB[''db''], param_str) client = pymongo.MongoClient(uri) 

假设 db 中有 collection 名为 TEST_COL,可以如下验证 client 的有效性:

    database = client[MONGODB[''db'']]
    print(database.TEST_COL.count())
    # client.run.command({''count'': ''TEST_COL''})    # 需要权限
    # client.admin.command(''ismaster'')             # 不支持副本集环境

4. 配置副本集读写分离

from pymongo import ReadPreference

db = conn.get_database(MONGODB[''db''], read_preference=ReadPreference.SECONDARY_PREFERRED)

副本集 ReadPreference 有 5 个选项:

  • PRIMARY:默认选项,从 primary 节点读取数据
  • PRIMARY_PREFERRED:优先从 primary 节点读取,如果没有 primary 节点,则从集群中可用的 secondary 节点读取
  • SECONDARY:从 secondary 节点读取数据
  • SECONDARY_PREFERRED:优先从 secondary 节点读取,如果没有可用的 secondary 节点,则从 primary 节点读取
  • NEAREST:从集群中可用的节点读取数据


作者:mona_alwyn
链接:https://www.jianshu.com/p/d9918b0a3ebc
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

bash – 如何在smb:// URL的密码字段中转义@符号

bash – 如何在smb:// URL的密码字段中转义@符号

我正在尝试编写一个bash脚本,通过获取用户名和密码,然后再说$username:$password @ SERVERNAME,我连接到samba服务器.

但是,如果密码在其中有@,则会失败.有没有办法从bash中输出密码?

提前致谢

更新:
我正在设置这个网络打印机

lpadmin -p PRINTER -v smb://$username:$password@SERVER -E

除非$密码中有一个@符号,否则它可以工作. $username和$passwords变量是从阅读stdin得到的

啊,不,这实际上并不是引用Bash的问题,而是引用了Samba.你有这个:
lpadmin -p PRINTER -v smb://$username:$password@SERVER -E

哪个Bash完全扩展到

lpadmin -p PRINTER -v smb://alice:passw@rd@SERVER -E

然后Samba客户端库认为密码在第一个@符号结束,并且应该连接到名为rd @ server的服务器,不要忘记您不能将该名称放在DNS中.

lpadmin来自CUPS,而不是Samba(here is its manpage),并且通过这些文档读取,我想您可能可以使用这种替代语法:

lpadmin -p PRINTER -U "${username}%${password}" -v smb://SERVER -E

我很惊讶,因为@不工作,但是.看起来像samba客户端库中的一个bug给我.

golang使用mgo连接MongoDB

golang使用mgo连接MongoDB

github:https://github.com/ZhangzheBJUT/blog/blob/master/mgo.md 现在MongoDB官方还没有推出关于官方支持的golang的driver,推荐使用的是mgo. mgo的详细文档说明:http://godoc.org/labix.org/v2/mgo 下面是我开发中自己写的一个用mgo连接MongoDB数据库的使

github:https://github.com/ZhangzheBJUT/blog/blob/master/mgo.md

现在MongoDB官方还没有推出关于官方支持的golang的driver,推荐使用的是mgo. mgo的详细文档说明:http://godoc.org/labix.org/v2/mgo
下面是我开发中自己写的一个用mgo连接MongoDB数据库的使用实例。
package main

import (

    "fmt"
    "labix.org/v2/mgo"
    "labix.org/v2/mgo/bson"
)

type Person struct {
    NAME  string
    PHONE string
}
type Men struct {
    Persons []Person
}
const = (
    URL = "192.168.2.175:27017"
)
func main() {

    session, err := mgo.Dial(URL)  //连接数据库
    if err != nil {
        panic(err)
    }
    defer session.Close()
    session.SetMode(mgo.Monotonic, true)

    db := session.DB("mydb")     //数据库名称
    collection := db.C("person") //如果该集合已经存在的话,则直接返回


    //*****集合中元素数目********
    countNum, err := collection.Count()
    if err != nil {
        panic(err)
    }
    fmt.Println("Things objects count: ", countNum)

    //*******插入元素*******
    temp := &Person{
        PHONE: "18811577546",
        NAME:  "zhangzheHero"
    }
        //一次可以插入多个对象 插入两个Person对象
    err = collection.Insert(&Person{"Ale", "+55 53 8116 9639"}, temp)
    if err != nil {
        panic(err)
    }

    //*****查询单条数据*******
    result := Person{}
    err = collection.Find(bson.M{"phone": "456"}).One(&result)
    fmt.Println("Phone:", result.NAME, result.PHONE)

    //*****查询多条数据*******
    var personAll Men  //存放结果
    iter := collection.Find(nil).Iter()
    for iter.Next(&result) {
        fmt.Printf("Result: %v\n", result.NAME)
        personAll.Persons = append(personAll.Persons, result)
    }

    //*******更新数据**********
    err = collection.Update(bson.M{"name": "ccc"}, bson.M{"$set": bson.M{"name": "ddd"}})
    err = collection.Update(bson.M{"name": "ddd"}, bson.M{"$set": bson.M{"phone": "12345678"}})
    err = collection.Update(bson.M{"name": "aaa"}, bson.M{"phone": "1245", "name": "bbb"})

    //******删除数据************
    _, err = collection.RemoveAll(bson.M{"name": "Ale”})
登录后复制
} 
登录后复制

Mongodb-- python中使用pymongo连接mongodb数据库

Mongodb-- python中使用pymongo连接mongodb数据库

一.使用

通过pip或者pychrm下载pymongo模块

import json

from pymongo import MongoClient
from bson import ObjectId

mc = MongoClient("127.0.0.1",27017)
MONGODB = mc["数据库名"]

MONGODB.users.find({}) # 可以操作了

上面的文件一般单独写一个settings.py,在用到的时候,通过引入MONGO来操作

关于bson:

  mongo中取出的数据有一个''_id''字段相当于mysql中的id, 这个字段的类型是Objectid,所以查询的结果不能直接json序列化,需要将这个''_id''转化为str类型后才能json序列化,相应的,从前端传过来的''_id''也要通过bson转化为ObjectId才能查到Mongodb中的数据

@au.route(''/auto_login'',methods=[''POST''])
def auto_login():
    user_info = request.form.to_dict()
    print(user_info)

    try:
        user_id = user_info.get(''user_id'')
        user = MONGODB.users.find_one({''_id'': ObjectId(user_id)})
        user[''_id''] = str(user[''_id''])
        RET = {
            ''code'': 1,
            ''msg'': ''自动登陆成功'',
            ''data'': user
        }
    except:
        RET = {
            ''code'': 0,
            ''msg'': ''自动登陆失败'',
            ''data'': {}
        }

    return jsonify(RET)

 

操作示例

# MONGODB = mc["admin"]
# res = MONGODB.users.find_one({"name":"Tom"})
# res["cours"].append({"name":"Tom","money":"100"})
# for index,cours in enumerate(res["cours"]):
#     if cours.get("name") == "Tom":
#         res["cours"][index]["score"] = 99


# MONGODB.users.delete_one({"age":84})
# MONGODB.users.delete_many({"age":84})

# user = MONGODB.users.find_one({"_id":ObjectId("5cb6eb7322b9441020186701")})
# print(user.get("_id"),type(user.get("_id")))
#
# user["_id"] = str(user["_id"])
# jsonstr = json.dumps(user)
# print(jsonstr , type(jsonstr))

 

关于如何在pymongo连接中的密码中转义@?python密码密文转换的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于(原创) 使用 pymongo 3.6.0 连接 MongoDB 的正确姿势、bash – 如何在smb:// URL的密码字段中转义@符号、golang使用mgo连接MongoDB、Mongodb-- python中使用pymongo连接mongodb数据库等相关内容,可以在本站寻找。

本文标签: