[Python] "TypeError: string argument without an encoding" when retrieving an ORM object

Discussão em 'Python' iniciado por Stack, Setembro 30, 2024.

  1. Stack

    Stack Membro Participativo

    I'm trying to set up an SFTP server in python, using paramiko library. I'm using a PostgreSQL to store users credentials, by SQLAlchemy library.

    When I try to login using FileZilla or WinSCP to the server, it gives me an error in this function:

    def authenticate_user(username: str, password:str = None, public_key:str = None) -> bool:
    engine = provide_engine()
    if not engine:
    return False

    Session = sessionmaker(bind=engine)
    session = Session()

    try:
    stmt = select(User).where(User.username == username)
    user = session.execute(stmt).scalars().first()

    if not user:
    return False

    if password:
    print("Before checking.")
    if user.check_password(password):
    print("After checking.")
    return True
    elif public_key and user.ssh_keys and len(user.ssh_keys) > 0:
    for key in user.ssh_keys:
    if key.public_key == public_key:
    return True

    return False
    finally:
    session.close()


    The error is:

    ERROR:paramiko.transport:Unknown exception: string argument without an encoding
    ERROR:paramiko.transport:Traceback (most recent call last):
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\paramiko\transport.py", line 2262, in run
    ERROR:paramiko.transport: handler(m)
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\paramiko\auth_handler.py", line 609, in _parse_userauth_request
    ERROR:paramiko.transport: result = self.transport.server_object.check_auth_password(
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "d:\Files\*******\Python\cr-beta\database_sftp\SFTPServer.py", line 20, in check_auth_password
    ERROR:paramiko.transport: if authenticate_user(username, password=password):
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "d:\Files\*******\Python\cr-beta\database_sftp\SFTPServer.py", line 98, in authenticate_user
    ERROR:paramiko.transport: user = session.execute(stmt).scalars().first()
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\sqlalchemy\engine\result.py", line 1786, in first
    ERROR:paramiko.transport: return self._only_one_row(
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\sqlalchemy\engine\result.py", line 749, in _only_one_row
    ERROR:paramiko.transport: row: Optional[_InterimRowType[Any]] = onerow(hard_close=True)
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\sqlalchemy\engine\result.py", line 1673, in _fetchone_impl
    ERROR:paramiko.transport: return self._real_result._fetchone_impl(hard_close=hard_close)
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\sqlalchemy\engine\result.py", line 2259, in _fetchone_impl
    ERROR:paramiko.transport: row = next(self.iterator, _NO_ROW)
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\sqlalchemy\orm\loading.py", line 219, in chunks
    ERROR:paramiko.transport: fetch = cursor._raw_all_rows()
    ERROR:paramiko.transport: ^^^^^^^^^^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\sqlalchemy\engine\result.py", line 541, in _raw_all_rows
    ERROR:paramiko.transport: return [make_row(row) for row in rows]
    ERROR:paramiko.transport: ^^^^^^^^^^^^^
    ERROR:paramiko.transport: File "lib\\sqlalchemy\\cyextension\\resultproxy.pyx", line 22, in sqlalchemy.cyextension.resultproxy.BaseRow.__init__
    ERROR:paramiko.transport: File "lib\\sqlalchemy\\cyextension\\resultproxy.pyx", line 79, in sqlalchemy.cyextension.resultproxy._apply_processors
    ERROR:paramiko.transport: File "C:\Users\*******\AppData\Local\Programs\Python\Python312\Lib\site-packages\sqlalchemy\sql\sqltypes.py", line 913, in process
    ERROR:paramiko.transport: value = bytes(value)
    ERROR:paramiko.transport: ^^^^^^^^^^^^
    ERROR:paramiko.transport:TypeError: string argument without an encoding


    I don't understand wher is the problem, also because, the username is stored as string in the Database, and the password i think that is handled well. Under the declaraton of the User table:

    class User(Base):
    __tablename__ = USERS_TABLE
    id = Column(Integer, primary_key=True)
    username = Column(String, unique=True, nullable=False)
    password_hash = Column(LargeBinary, nullable=False)
    created_at = Column(DateTime, default=datetime.now(timezone.utc))

    ssh_keys = relationship("SSHKey", back_populates="user")

    def set_hashed_password(self, hashed_password: bytes):
    self.password_hash = hashed_password

    def set_password(self, password: str):
    self.password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt())

    def check_password(self, password: str) -> bool:
    return bcrypt.checkpw(password.encode(), self.password_hash)


    I want to specify that i'm trying to login with a username and a password, and not with a ssh key.

    UPDATE: I tried to check the real column type using:

    from sqlalchemy import inspect
    insp = inspect(engine)
    print(list(x["type"] for x in insp.get_columns(USERS_TABLE) if x["name"] == "password_hash"))


    and it print [VARCHAR()] in console.

    I also check in pgAdmin4 and the type of the column is character varying.

    [​IMG]

    Why if in User class I set column as LargeBinary it is a variable character? Is this the problem?

    Continue reading...

Compartilhe esta Página