如果您对如何在pymongo连接中的密码中转义@?感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于如何在pymongo连接中的密码中转义@?的详细内容,我们还将为您解答pyt
如果您对如何在pymongo连接中的密码中转义@?感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于如何在pymongo连接中的密码中转义@?的详细内容,我们还将为您解答python密码密文转换的相关问题,并且为您提供关于(原创) 使用 pymongo 3.6.0 连接 MongoDB 的正确姿势、bash – 如何在smb:// URL的密码字段中转义@符号、golang使用mgo连接MongoDB、Mongodb-- python中使用pymongo连接mongodb数据库的有价值信息。
本文目录一览:- 如何在pymongo连接中的密码中转义@?(python密码密文转换)
- (原创) 使用 pymongo 3.6.0 连接 MongoDB 的正确姿势
- bash – 如何在smb:// URL的密码字段中转义@符号
- golang使用mgo连接MongoDB
- Mongodb-- python中使用pymongo连接mongodb数据库
如何在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 的正确姿势
0. 疑惑
前两天使用 pymongo 连接 MongoDB 的时候发现了一个奇怪的现象:我本机 MongoDB 并没有打开,但是使用 pymong.MongoClient () 进行连接时,并没有异常,我的服务端也正常跑起来了,直到收到请求,进行数据库查询操作的时候,等了相当长的一段时间之后,服务端才由于 MongoDB 连接不上报异常。
Note: 本机环境pymongo 3.6.0,MongoDB 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. 解答
那这是为什么呢?
按一般的理解,MongoClient 接口实现的时候肯定要考虑 MongoDB 连接异常的情况,只有确保连接成功建立,才能一步一步往下取 database、取 collection、基于 collection 进行增删改查操作等等。
这里为什么不呢 ?我发现了一个大 BUG?不应该啊,pymongo 发布使用的时间比我用 Python 写代码都要长,这要是 bug 早该解决了。
如何使用 pymongo 连接 MongoDB,网上确实有很多很多博客,不过绝大多数都很简单,基本就我上面那几行的正确使用而已,顶多再提醒一下安装 pymongo 的时候不能安装第三方 bson,因为 pymongo 自带 bson,两者不匹配,讲如何进行密码验证的都很少,更别说 replSet 参数的使用。
终于还是在官网的 API 接口文档中 MongoClient 的解释中找到了答案:
简单翻译一下:
从 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 和图 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'', ...)
-
- "mongodb+srv://"
这种形式的 URL 只支持一个 hostname,对应 DNS server,进行 SRV record 查询,它也支持 replSet 和 authSource(TXT record),需要注意的是它默认使用 TLS,即 ssl=True。
具体的说明还是看 initial-dns-seedlist-discovery
假设我们使用
- "mongodb+srv://"
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
-
- SSL
一堆的参数,还没有用过,自行看文档吧。
- 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中输出密码?
提前致谢
更新:
我正在设置这个网络打印机
lpadmin -p PRINTER -v smb://$username:$password@SERVER -E
除非$密码中有一个@符号,否则它可以工作. $username和$passwords变量是从阅读stdin得到的
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
github:https://github.com/ZhangzheBJUT/blog/blob/master/mgo.md 现在MongoDB官方还没有推出关于官方支持的
现在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数据库
一.使用
通过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数据库等相关内容,可以在本站寻找。
本文标签: