2017-01-10 50 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 

但復歸只是一種變通方法,你應該在你的代碼中跟蹤你建立一個字節字符串的表示