2017-10-13 163 views
0

我想知道如何將用戶名轉移到另一個文件。但是,如果沒有整個腳本,我只希望能夠導入該變量。Python,導入文件

到目前爲止,用戶必須設置他們希望使用的用戶名,然後他們必須爲此設置密碼。如何導入該用戶名變量,但輸入數據時是否將輸入的數據存儲在該變量中?

的用戶名密碼爲:

set_username = input("First enter a username you wish to use: ") 
set_password = input("Now enter a password you wish to use: ") 

然後,在另一個文件中,用戶需要使用用戶名和密碼登錄,他們在另一個文件中的設置。我該如何導入用戶已設置的用戶名和密碼變量,並且數據仍存儲在這些變量中。

+0

您可以將用戶/密碼列表寫入文件並從該文件中讀取該列表,但這[不是應該如何完成的](https://www.youtube.com/watch?v=8ZtInClXe1Q) 。應該保留用戶列表,以及指向巫婆文件/文件夾屬於該用戶的指針。該文件/文件夾的內容應使用第一種情況下給出的密碼進行加密,如果提供了正確的密碼,解密應該是成功的。 – berna1111

+0

順便說一下,我相信加密模塊是[hashlib](https://docs.python.org/2/library/hashlib.html#module-hashlib) - 我從來沒有使用它,但就我而言從第一眼就明白它是用來散列給定的密鑰(不像我在之前的評論中所說的那樣是文件或文件夾)。您保留密碼的結果散列,並且您在嘗試用於登錄的任何密碼上使用相同的散列函數。 – berna1111

+0

好的感謝您的幫助,可能聽起來像一個愚蠢的問題,但我只是進入編程。但再次感謝回覆 – Jake

回答

1

您可以在原始文件中創建一個函數來獲取/返回用戶名和密碼。然後你可以在你的其他文件中導入這個函數。例如,

def get_username(): 
    return set_username 

def get_password(): 
    return set_password 

然後在你的其他的文件,你可以說,

from filename import get_username, get_password 
1

到@agaidis答案類似,您還可以導入變量,而無需使用get函數:

from filename import set_username, set_password 
0

有興趣並做了一個令人費解的例子:定義了一個LoginManager類來處理使用外部文檔上的列表創建和記錄用戶。這個類應該保存在它自己的文件中,然後將其導入創建新用戶的代碼文件和驗證它們的代碼文件中(請參閱代碼示例)。

類啓動程序獲取文件路徑作爲參數,只要它指向兩個代碼文件中的同一個文件,它應該可以。

我用argon2作爲散列算法,雖然我必須承認我是密碼學的新手,所以你應該用一粒鹽來看待我的選擇。

import argon2 
from pathlib import Path 
import re 


class LoginManager(object): 
    """ 
    Parameters 
    ---------- 
    database : str 
     File (and path to it) that holds the users and corresponding hashed 
     passwords. 

    Examples 
    -------- 
    Simple `LoginManager`: 

    >>> temp_database = 'temp_database.txt' 
    >>> Login1 = LoginManager(temp_database) 
    >>> Login1.add_user('super_user', 's3kr3tp4ssw0rd') 
    >>> Login1.login('super_user', 's3kr3tp4ssw0rd') 
    True 
    >>> Login1.login('super_user', 't0t411ywr0ng') # wrong password 
    False 
    >>> Login1.login('LameUser', 's3kr3tp4ssw0rd') # not existing user 
    False 

    New `LoginManager` with the same database: 

    >>> Login2 = LoginManager(temp_database) 
    >>> Login2.login('super_user', 's3kr3tp4ssw0rd') # was on Login1 
    True 
    >>> Login2.login('super_user', 't0t411ywr0ng') # wrong password 
    False 
    >>> Login2.login('LameUser', 't0t411ywr0ng') # not existing user 
    False 

    Clean `temp_database` if testing with `doctest`: 

    >>> import os 
    >>> os.remove(temp_database) 


    Notes 
    ----- 
    * Notice that adding new users to either LoginManager in the example will 
     not share the new ones between them! Only the users existing at the time 
     of the creation will be in the LoginManager, so colisions must be must be 
     avoided by not having two pointing to the same file at the same. 
    * See more details on `argon2` here: 
     https://argon2-cffi.readthedocs.io/en/stable/api.html#argon2.PasswordHasher 
     (also where I saw 's3kr3tp4ssw0rd' and 't0t411ywr0ng') 
    """ 
    def __init__(self, database=None): 
     """ 
     Create new `LoginManager`. 

     Notes 
     ----- 
     Should have better verification whether given path points to a file or 
     a folder! 
     """ 
     if database is None: 
      database = 'database.txt' 
     self.database = Path(database) 
     # create file if it is not there: 
     if not self.database.is_file(): 
      self.database.touch() 

     self._reload_database() 

     self.hasher = argon2.PasswordHasher(time_cost=2, 
              memory_cost=512, 
              parallelism=2, 
              hash_len=16, 
              salt_len=16, 
              encoding='utf-8') 
     self._hash_example = self.hasher.hash('default') 
     self._max_name_size = 10 

    def add_user(self, user, password): 
     """ 
     Add new user to the `LoginManager` and update `database` file. 
     Raises `ValueError` if the user already exists or is invalid. 

     Examples 
     -------- 
     >>> temp_database = 'temp_database_user.txt' 
     >>> Login1 = LoginManager(temp_database) 
     >>> Login1.add_user('super*user', 's3kr3tp4ssw0rd') 
     Traceback (most recent call last): 
     ValueError: Invalid characters in user name! 
     Use only A-Z, a-z, 0-9 and `.`, `-` or `_`. 
     >>> Login1.add_user('UltraLongUserName', 's3kr3tp4ssw0rd') 
     Traceback (most recent call last): 
     ValueError: User name "UltraLongUs..." too long! 

     Clean `temp_database` if testing with `doctest`: 

     >>> import os 
     >>> os.remove(temp_database) 

     Notes 
     ----- 
     Does not check users added to the databse file after the `LoginManager` 
     was created! 
     """ 
     self._is_username_valid(user) # raises ValueError if it's not 
     hashed = self.hasher.hash(password) 
     self.users[user] = hashed 
     with self.database.open('ba') as database: 
      database.write('\t'.join([user.ljust(self._max_name_size), 
             hashed, 
             '\r\n'])) 
     # The '\r\n' at the end ensures there's always a new empty line 
     # after the lattest password, and eases the split of user name and 
     # password afterwards using '\t' when importing the list. 
     # The .ljust(self._max_name_size) pads the username with spaces. 
     # The binary mode is used to ensure future changes are valid (namely 
     # to allow the use of seek with negative values whithin the file. 

    def login(self, user, password): 
     """ 
     Return `True` if the user/password pair is valid, `False` otherwise. 
     """ 
     try: 
      return self.hasher.verify(self.users.get(user, self._hash_example), 
             password) 
     except argon2.exceptions.VerifyMismatchError: 
      return False 

    def change_password(self, user, old_password, new_password): 
     """ 
     Change password of existing user. 

     Examples 
     -------- 
     >>> temp_database = 'temp_database_change_pass.txt' 
     >>> Login1 = LoginManager(temp_database) 
     >>> Login1.add_user('super_user', 's3kr3tp4ssw0rd') 
     >>> Login1.add_user('LameUser', 't0t411ywr0ng') 
     >>> Login1.add_user('banana', '1234567890') 

     Test changes to first user: 

     >>> Login1.login('super_user', 's3kr3tp4ssw0rd') 
     True 
     >>> Login1.change_password('super_user', 
     ...      's3kr3tp4ssw0rd', 
     ...      'n3ws3kr3tp4ssw0rd') 
     >>> Login1.login('super_user', 's3kr3tp4ssw0rd') 
     False 
     >>> Login1.login('super_user', 'n3ws3kr3tp4ssw0rd') 
     True 

     Test changes to last user: 

     >>> Login1.change_password('banana', 
     ...      '1234567890', 
     ...      'n3ws3kr3tp4ssw0rd') 
     >>> Login1.login('banana', '1234567890') 
     False 
     >>> Login1.login('banana', 'n3ws3kr3tp4ssw0rd') 
     True 

     Test changes to a middle user: 

     >>> Login1.change_password('LameUser', 
     ...      't0t411ywr0ng', 
     ...      'n3ws3kr3tp4ssw0rd') 
     >>> Login1.login('banana', 't0t411ywr0ng') 
     False 
     >>> Login1.login('banana', 'n3ws3kr3tp4ssw0rd') 
     True 


     Make sure changes to file are valid: 

     >>> Login2 = LoginManager(temp_database) 
     >>> Login2.login('super_user', 'n3ws3kr3tp4ssw0rd') 
     True 

     Clean `temp_database` if testing with `doctest`: 

     >>> import os 
     >>> os.remove(temp_database) 

     Notes 
     ----- 
     If a contact is available to reach the user, it should be used to warn 
     him of an attempt to change the password. 
     """ 
     if self.login(user, old_password): 
      with self.database.open('br+') as database: 
       # find user name 
       line = ' ' 
       while line != '': 
        line = database.readline() 
        if line[:self._max_name_size].rstrip() == user: 
         new_hash = self.hasher.hash(new_password) 
         database.seek(-len(self._hash_example)-3, 1) 
         database.write('\t'.join([new_hash, '\r\n'])) 
         self.users[user] = new_hash 
         break 

    def _reload_database(self): 
     self.users = {} # could use a more intuitive name 
     with self.database.open('r') as database: 
      lines = database.readlines() 
      for user_pass in lines: 
       user, pass_hash, new_line = user_pass.split('\t') 
       self.users[user.rstrip()] = pass_hash 

    def _is_username_valid(self, user_name): 
     """ 
     Check if user name is valid, raise `ValueError` if it's not. 
     """ 
     if user_name in self.users.keys(): 
      raise ValueError('User "%s" already exists!' % (user_name,)) 

     if len(user_name) > self._max_name_size: 
      raise ValueError('User name "%s..." too long!' % 
          (user_name[:self._max_name_size+1],)) 

     # From https://stackoverflow.com/questions/1323364/ 
     search = re.compile(r'[^A-Za-z0-9._-]').search 
     if bool(search(user_name)): 
      raise ValueError('Invalid characters in user name!\n' 
          'Use only A-Z, a-z, 0-9 and `.`, `-` or `_`.') 


def _test(): 
    """ 
    Test functions using the doctext examples. 
    """ 
    import doctest 
    doctest.testmod(verbose=False) 


if __name__ == "__main__": 
    # use the examples in documentation to test the code. 
    _test() 

你(和任何人)是自由活動,使用和改變,但不要把這個作爲一個很好的做法的例子 - 只是一個業餘愛好者對這個問題的看法。