Tkinter password entry form

TrustyTony 0 Tallied Votes 10K Views Share

Inspired by password entry discussions, I did this simple entry. You must of course find safe way to store the passwords, for example hashlib (http://stackoverflow.com/questions/4820043/basics-of-python-encryption-w-hashlib-sha1) or PyCrypto and replace the simplistic example match for real life usage.

The print at line 23 is just to check the attempts and to see the text really was received correctly by the program.

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk
# from http://effbot.org/tkinterbook/entry.htm

failure_max = 3
passwords = [('DaniWeb', 'best1'), ('newbie', 'help!help!')]

def make_entry(parent, caption, width=None, **options):
    tk.Label(parent, text=caption).pack(side=tk.TOP)
    entry = tk.Entry(parent, **options)
    if width:
        entry.config(width=width)
    entry.pack(side=tk.TOP, padx=10, fill=tk.BOTH)
    return entry

def enter(event):
    check_password()

def check_password(failures=[]):
    """ Collect 1's for every failure and quit program in case of failure_max failures """
    print(user.get(), password.get())
    if (user.get(), password.get()) in passwords:
        root.destroy()
        print('Logged in')
        return
    failures.append(1)
    if sum(failures) >= failure_max:
        root.destroy()
        raise SystemExit('Unauthorized login attempt')
    else:
        root.title('Try again. Attempt %i/%i' % (sum(failures)+1, failure_max))
    

root = tk.Tk()
root.geometry('300x160')
root.title('Enter your information')
#frame for window margin
parent = tk.Frame(root, padx=10, pady=10)
parent.pack(fill=tk.BOTH, expand=True)
#entrys with not shown text
user = make_entry(parent, "User name:", 16, show='*')
password = make_entry(parent, "Password:", 16, show="*")
#button to attempt to login
b = tk.Button(parent, borderwidth=4, text="Login", width=10, pady=8, command=check_password)
b.pack(side=tk.BOTTOM)
password.bind('<Return>', enter)

user.focus_set()

parent.mainloop()
TrustyTony 888 ex-Moderator Team Colleague Featured Poster

It looks like magic at first how keyword parameter with list value keeps its value across calls. Here is version of code which use 'function as object' and stores value as attribute of the function, and usage example (practically maybe it would be safer the code to be included in code itself and not used as module, but principle is same, and this is yet intrinsically unsafe as passwords are visible in source code.

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk
# from http://effbot.org/tkinterbook/entry.htm

failure_max = 3
passwords = [('DaniWeb', 'best1'), ('newbie', 'help!help!')]

def make_entry(parent, caption, width=None, **options):
    tk.Label(parent, text=caption).pack(side=tk.TOP)
    entry = tk.Entry(parent, **options)
    if width:
        entry.config(width=width)
    entry.pack(side=tk.TOP, padx=10, fill=tk.BOTH)
    return entry

def enter(event):
    check_password()

def check_password():
    """ Collect 1's for every failure and quit program in case of failure_max failures """
    #print(user.get(), password.get())
    if (user.get(), password.get()) in passwords:
        check_password.user = user.get()
        root.destroy()
        print('Logged in')
        return
    check_password.failures += 1
    if check_password.failures == failure_max:
        root.destroy()
        raise SystemExit('Unauthorized login attempt')
    else:
        root.title('Try again. Attempt %i/%i' % (check_password.failures + 1, failure_max))
check_password.failures = 0

root = tk.Tk()
root.geometry('300x160')
root.title('Enter your information')
#frame for window margin
parent = tk.Frame(root, padx=10, pady=10)
parent.pack(fill=tk.BOTH, expand=True)
#entrys with not shown text
user = make_entry(parent, "User name:", 16, show='*')
password = make_entry(parent, "Password:", 16, show="*")
#button to attempt to login
b = tk.Button(parent, borderwidth=4, text="Login", width=10, pady=8, command=check_password)
b.pack(side=tk.BOTTOM)
password.bind('<Return>', enter)

user.focus_set()

parent.mainloop()

Usage assuming that above code can be found by import as tkPasswd

import time

try:
    import tk_passwd
except SystemExit as e:
    print(e)
else:   
    user = tk_passwd.check_password.user
    print('Welcome to IRS Tax Database, %s!' % user)
    time.sleep(4)
    print('Just kidding!')
Member Avatar for Enalicho
Enalicho

As a note, you probably wouldn't want to hide the user field, and use a class, but a good simple example for people to use.

TrustyTony 888 ex-Moderator Team Colleague Featured Poster

You can choose your way but knowing username is making breaking easier. For example internet service of my bank is hiding both user code and single use pin number.

Member Avatar for Enalicho
Enalicho

You can choose your way but knowing username is making breaking easier. For example internet service of my bank is hiding both user code and single use pin number.

Just making them stars does very little but providing the *allusion* of protection :) Encrypting them, however, will help (provide it's done correctly)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.