2017-04-21 32 views
2

我想在python中寫一個連接到BOX的小腳本,但它一直給我這個錯誤:'NoneType'對象沒有屬性'編碼'Boxsdk JWTAuth總是給我這個錯誤:'NoneType'對象沒有屬性'編碼'

起初我以爲這是我編碼密碼時造成的,但事實似乎並非如此。當我嘗試使用access_token = auth.authenticate_instance()進行身份驗證時,該腳本失敗。如果我沒有運行該腳本似乎工作。什麼可能導致這個?

在此先感謝您提供的任何幫助。

這是我有:

import keyring 
from boxsdk import JWTAuth 
from boxsdk import Client 

def read_tokens(): 
    """Reads authorisation tokens from keyring""" 
    # Use keyring to read the tokens 
    auth_token = keyring.get_password('Box_Auth', '[email protected]') 
    refresh_token = keyring.get_password('Box_Refresh', '[email protected]') 
    return auth_token, refresh_token 


def store_tokens(access_token, refresh_token): 
    """Callback function when Box SDK refreshes tokens""" 
    # Use keyring to store the tokens 
    keyring.set_password('Box_Auth', '[email protected]', access_token) 
    keyring.set_password('Box_Refresh', '[email protected]', refresh_token) 

Passphrase = 'xxxxxxx'; 
my_str_as_bytes = Passphrase.encode('UTF-8','strict') 

auth = JWTAuth(
    client_id='xxxxxxxxxx', 
    client_secret='xxxxxxxx', 
    enterprise_id='xxxxxxx', 
    jwt_key_id='xxxxxxx', 
    rsa_private_key_file_sys_path='/home/Marketscale/keys/private_key2.pem', 
    rsa_private_key_passphrase=my_str_as_bytes, 
    store_tokens=store_tokens, 
) 

access_token = auth.authenticate_instance() 

這是錯誤的全文:

Traceback (most recent call last): 
    File "/home/Marketscale/Tests/JWTTest.py", line 37, in <module> 
    access_token = auth.authenticate_instance() 
    File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/boxsdk/auth/jwt_auth.py", line 186, in authenticate_instance 
    return self._auth_with_jwt(self._enterprise_id, 'enterprise') 
    File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/boxsdk/auth/jwt_auth.py", line 158, in _auth_with_jwt 
    return self.send_token_request(data, access_token=None, expect_refresh_token=False)[0] 
    File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/boxsdk/auth/oauth2.py", line 298, in send_token_request 
    self._store_tokens(access_token, refresh_token) 
    File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/boxsdk/auth/oauth2.py", line 233, in _store_tokens 
    self._store_tokens_callback(access_token, refresh_token) 
    File "/home/Marketscale/Tests/JWTTest.py", line 22, in store_tokens 
    keyring.set_password('Box_Refresh', '[email protected]', refresh_token) 
    File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/keyring/core.py", line 48, in set_password 
    _keyring_backend.set_password(service_name, username, password) 
    File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/keyrings/alt/file_base.py", line 128, in set_password 
    password_encrypted = self.encrypt(password.encode('utf-8'), assoc) 
AttributeError: 'NoneType' object has no attribute 'encode' 

回答

1

我不知道你正在使用的所有的API,但也有少數基於看代碼的想法:

通過堆棧跟蹤從下往上的工作,你必須:

File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/keyrings/alt/file_base.py", line 128, in set_password 
    password_encrypted = self.encrypt(password.encode('utf-8'), assoc) 
AttributeError: 'NoneType' object has no attribute 'encode' 

該代碼位於https://github.com/jaraco/keyrings.alt/blob/master/keyrings/alt/file_base.py,密碼(我們知道它是None)是傳遞給set_password函數的最後一個參數。

File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/keyring/core.py", line 48, in set_password 
    _keyring_backend.set_password(service_name, username, password) 

該代碼是https://github.com/jaraco/keyring/blob/master/keyring/core.py,密碼又是到set_password函數的最後一個參數:即從調用。接下來,我們有:

File "/home/Marketscale/Tests/JWTTest.py", line 22, in store_tokens 
    keyring.set_password('Box_Refresh', '[email protected]', refresh_token) 

....這是你的代碼,所以refresh_token一定是None。這意味着你的store_tokens必須被調用了一個沒有None的refresh_token。下一頁:

File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/boxsdk/auth/oauth2.py", line 233, in _store_tokens 
    self._store_tokens_callback(access_token, refresh_token) 

這是在https://github.com/box/box-python-sdk/blob/master/boxsdk/auth/oauth2.py,並再次表示_store_tokens被稱爲與refresh_token設置爲無。起...

File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/boxsdk/auth/oauth2.py", line 298, in send_token_request 
    self._store_tokens(access_token, refresh_token) 

代碼相同的頁面上的最後一個,但現在它是一個更有趣:

 url = '{base_auth_url}/token'.format(base_auth_url=API.OAUTH2_API_URL) 
     headers = {'content-type': 'application/x-www-form-urlencoded'} 
     network_response = self._network_layer.request(
      'POST', 
      url, 
      data=data, 
      headers=headers, 
      access_token=access_token, 
     ) 
     if not network_response.ok: 
      raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST') 
     try: 
      response = network_response.json() 
      access_token = response['access_token'] 
      refresh_token = response.get('refresh_token', None) 
      if refresh_token is None and expect_refresh_token: 
       raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST') 
     except (ValueError, KeyError): 
      raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST') 
     self._store_tokens(access_token, refresh_token) 
     return self._access_token, self._refresh_token 

所以我們知道self._store_tokens被稱爲與refresh_token設置爲無,這意味着expect_refresh_token一定是False,否則BoxOAuthException會被引發。而且,事實上,如果我們看一下在堆棧跟蹤下一行了,我們可以看到:

File "/home/Marketscale/.virtualenvs/myvirtualenv/lib/python3.5/site-packages/boxsdk/auth/jwt_auth.py", line 158, in _auth_with_jwt 
    return self.send_token_request(data, access_token=None, expect_refresh_token=False)[0] 

這表明,我認爲,當你使用JWT驗證,你不能指望一個刷新令牌。並且,當您將None作爲密碼傳遞給密鑰環時,文件後端會爆炸,這聽起來像您需要以不同方式處理None情況。所以,我建議改變store_tokens工作,你提供這麼要麼忽略了刷新令牌,如果是無,即:

def store_tokens(access_token, refresh_token): 
    """Callback function when Box SDK refreshes tokens""" 
    # Use keyring to store the tokens 
    keyring.set_password('Box_Auth', '[email protected]om', access_token) 
    if refresh_token is not None: 
     keyring.set_password('Box_Refresh', '[email protected]', refresh_token) 

...或使之轉化成無的東西,鑰匙環文件後端可以從容地處理 - 也許一個空字符串會做的伎倆:

def store_tokens(access_token, refresh_token): 
     """Callback function when Box SDK refreshes tokens""" 
     # Use keyring to store the tokens 
     keyring.set_password('Box_Auth', '[email protected]', access_token) 
     if refresh_token is None: 
      refresh_token = "" 
     keyring.set_password('Box_Refresh', '[email protected]', refresh_token) 

一個警告 - 就像我說的,我不知道這些API - - 既不是盒子,也不是你使用的鑰匙扣。但基於那裏的代碼,做這樣的事聽起來像是值得一試的。

相關問題