2017-01-10 80 views
0

我的代码是从单点登录功能,我给它一个字符串,而不是字节python 3打印字符串,并说字符串的类型是str?

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) 
+1

确切地说'有效载荷'是由_originally_定义的? –

+0

什么是“有效载荷”?你怎么得到的?创建简单的工作示例。 – furas

+0

@leaf有效载荷创建功能添加到帖子。它是在django unittest中创建的 – deltaskelta

回答

1

正如你​​通过该base64.encodestring(s)其是由文档生成是:

编码类字节对象S,它可以包含任意的二进制 数据,并返回包含base64编码数据字节,在每76个字节的输出之后插入 换行符(b'\ n'),并根据RFC 2045(MIME)确保 存在后续换行符。

然后你做urllib.parse.unquote到由ASCII字符组成的字节序列。在那一刻,你的字符串前缀为b',因为unquote在有效载荷bytearray上运行str构造函数。作为一个请求,你得到一个str而不是字节,而且这是一个无效的base64编码。

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) 
0

原来的允许误差认为,和编码字符串的显示证实了这一点:你的​​字符串一个unicode字符串,恰好以前缀"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

>>> b2 = ast.literal_eval(r) 
>>> type(b2) 
<class 'bytes'> 
>>> b == b2 
True 

但复归只是一种变通方法,你应该在你的代码中跟踪你建立一个字节字符串的表示