This article mainly introduces how to use Python to implement web-end user login and registration functions. if you need it, you can refer to user management, which is a problem that most Web websites need to solve. User management involves user registration and logon.
User registration is relatively simple. you can use the API to register a user:
_RE_MD5 = re.compile(r'^[0-9a-f]{32}$')@api@post('/api/users')def register_user(): i = ctx.request.input(name='', email='', password='') name = i.name.strip() email = i.email.strip().lower() password = i.password if not name: raise APIValueError('name') if not email or not _RE_EMAIL.match(email): raise APIValueError('email') if not password or not _RE_MD5.match(password): raise APIValueError('password') user = User.find_first('where email=?', email) if user: raise APIError('register:failed', 'email', 'Email is already in use.') user = User(name=name, email=email, password=password, image='http://www.gravatar.com/avatar/%s?d=mm&s=120' % hashlib.md5(email).hexdigest()) user.insert() return user
Note that the user password is a 32-bit Hash string passed by the client after MD5 calculation, so the server does not know the user's original password.
Next, you can create a registration page, ask the user to fill out the registration form, and then submit the data to the registered user's API:
{% Extends '{base=.html '%} {% block title %} register {% endblock %} {% block beforehead %} script function check_form () {$ ('# password '). val (CryptoJS. MD5 ($ ('# password1 '). val ()). toString (); return true;} script {% endblock %} {% block content %}Welcome to registration!
{% Endblock %} Try
In this way, the user registration function is completed:
User logon is more complex than user registration. Because HTTP is a stateless protocol, the server can only use cookies to track the user status. Most Web frameworks provide Session functions to encapsulate cookies that store user statuses.
Session is easy to use and can be used to retrieve user logon information from the Session.
The disadvantage of Session is that the server needs to maintain a ing table in the memory to store user login information. if there are more than two servers, it needs to cluster the Session. therefore, it is difficult to extend a Web App using Session.
We use the method of directly reading cookies to verify user logon. every time a user accesses any URL, the cookie will be verified. the advantage of this method is that the server is stateless when processing any URL, it can be expanded to multiple servers.
After successful login, the server generates a cookie and sends it to the browser. therefore, ensure that the cookie is not forged by the client.
The key to implementing anti-counterfeit cookie creation is to use a one-way algorithm (such as MD5), for example:
After the user enters the correct password for logon, the server can obtain the user id from the database and calculate a string as follows:
"User ID" + "Expiration Time" + MD5 ("User ID" + "user password" + "Expiration Time" + "SecretKey ")
After the browser sends a cookie to the server, the server can obtain the following information:
- User ID
- Expiration Time
- MD5 value
If the expiration time is not reached, the server searches for the user password based on the user ID and calculates:
MD5 ("User ID" + "user password" + "Expiration Time" + "SecretKey ")
And compare it with the MD5 in the browser cookie. if it is equal, it indicates that the user has logged on. Otherwise, the cookie is forged.
The key to this algorithm is that MD5 is a one-way algorithm, that is, MD5 can be calculated from the original string, but the original string cannot be reversed through MD5.
Therefore, you can log on to the API as follows:
@ Api @ post ('/api/authenticate') def authenticate (): I = ctx. request. input () email = I. email. strip (). lower () password = I. password user = User. find_first ('Where email =? ', Email) if user is None: raise APIError ('auth: failed', 'Email', 'invalid email. ') elif user. password! = Password: raise APIError ('auth: failed', 'password', 'invalidpassword. ') max_age = 604800 cookie = make_signed_cookie (user. id, user. password, max_age) ctx. response. set_cookie (_ COOKIE_NAME, cookie, max_age = max_age) user. password = ****** 'return user # Calculate the encryption cookie: def make_signed_cookie (id, password, max_age): expires = str (int (time. time () + max_age) L = [id, expires, hashlib. md5 ('% s-% s' % (Id, password, expires, _ COOKIE_KEY )). hexdigest ()] return '-'. join (L) for each URL processing function, if we write the code to parse the cookie, it will lead to code repeated many times. The interceptor parses the cookie before processing the URL and binds the login user to ctx. in this way, the subsequent URL processing function can directly obtain the login user: @ interceptor ('/') def user_interceptor (next): user = None cookie = ctx. request. cookies. get (_ COOKIE_NAME) if cookie: user = parse_signed_cookie (cookie) ctx. request. user = user return next () # decrypt cookie: def parse_signed_cookie (cookie_str): try: L = cookie_str.split ('-') if len (L )! = 3: return None id, expires, md5 = L if int (expires) <time. time (): return None user = User. get (id) if user is None: return None if md5! = Hashlib. md5 ('% s-% s' % (id, user. password, expires, _ COOKIE_KEY )). hexdigest (): return None return user failed t: return NoneTry
In this way, the user registration and login functions are completed.