我的代码来自单点登录功能
from urllib.parse import unquote
import base64
payload = unquote(payload)
print(payload)
print(type(payload))
decoded = base64.decodestring(payload)
decodestring抱怨我给它一个字符串而不是字节......
File "/Users/Jeff/Development/langalang/proj/discourse/views.py", line 38, in sso decoded = base64.decodestring(payload) File "/Users/Jeff/.virtualenvs/proj/lib/python3.6/base64.py", line 559, in decodestring return decodebytes(s) File "/Users/Jeff/.virtualenvs/proj/lib/python3.6/base64.py", line 551, in decodebytes _input_type_check(s) File "/Users/Jeff/.virtualenvs/proj/lib/python3.6/base64.py", line 520, in _input_type_check raise TypeError(msg) from err TypeError: expected bytes-like object, not str
这很好但是当我看到打印到终端的打印语句时,我看到了......
b'bm9uY2U9NDI5NDg5OTU0NjU4MjAzODkyNTI=\n'
<class 'str'>
似乎是说它是一串字节,但后来它说它是一个字符串。
这里发生了什么?
如果我在有效负载声明的末尾添加encode()
,我会看到这个......
payload = unquote(payload).encode()
b"b'bm9uY2U9NDQxMTQ4MzIyNDMwNjU3MjcyMDM=\\n'"
<class 'bytes'>
编辑:添加制作有效载荷的方法
@patch("discourse.views.HttpResponseRedirect")
def test_sso_success(self, mock_redirect):
"""Test for the sso view"""
# Generating a random number, encoding for url, signing it with a hash
nonce = "".join([str(random.randint(0, 9)) for i in range(20)])
# The sso payload needs to be a dict of params
params = {"nonce": nonce}
payload = base64.encodestring(urlencode(params).encode())
print(payload.decode() + " tests")
key = settings.SSO_SECRET
h = hmac.new(key.encode(), payload, digestmod=hashlib.sha256)
signature = h.hexdigest()
url = reverse("discourse:sso") + "?sso=%s&sig=%s" % (payload, signature)
req = self.rf.get(url)
req.user = self.user
response = sso(req)
self.assertTrue(mock_redirect.called)
答案 0 :(得分:1)
似乎是说它是一串字节,但后来它说它是一个字符串。
看起来你在这里的字符串看起来像:"b'bm9uY2U9NDQxMTQ4MzIyNDMwNjU3MjcyMDM=\\n'"
所以前导b不是字节文字,它只是字符串值的一部分。
因此,在将符号传递给base64解码器之前,您需要先将其删除:
from urllib.parse import unquote, quote_from_bytes
import base64
payload = unquote(payload)
print(payload[2:-1])
enc = base64.decodebytes(payload[2:-1].encode())
print(enc)
答案 1 :(得分:1)
当您payload
生成base64.encodestring(s)
时,文档是:
对类似字节的对象进行编码,该对象可以包含任意二进制文件 数据,以及包含base64编码数据的返回字节 在每76个字节的输出之后插入换行符(b'\ n')并确保 根据RFC 2045(MIME),有一个尾随换行符。
然后对{ASCII}字符序列进行urllib.parse.unquote
。在那一刻,你的字符串前缀为b'
,因为unquote在有效负载bytearray上运行str构造函数。作为一个请求,你得到一个str而不是字节,而且这是一个无效的base64编码。
答案 2 :(得分:0)
允许原始错误认为,并且编码字符串的显示确认了它:您的payload
字符串 是一个unicode字符串,恰好以前缀{{1}开头并以单个"b'"
结尾。
这样的字符串通常使用"'"
调用构建:
repr
您可以使用>>> b = b'abc' # b is a byte string
>>> r = repr(b) # by construction r is a unicode string
>>> print(r) # will look like a byte string
b'abc'
>>> print(b) # what is printed for a true byte string
abc
恢复为真正的字节字符串:
literal_eval
但是还原只是一种解决方法,您应该在代码中跟踪您构建字节字符串的表示。