(According to the content of teacher's live broadcast)
One, user login
1. Logical analysis of user name login
2. Username login interface design
2.1 Request method
Options
Program
Request method
POST
Request address
/sessions
2.2 Request parameters: form
parameter name
Types of
Must pass
Description
mobile
string
Yes
phone number
password
string
Yes
password
2.3 Response result: HTML
Field
Description
Login failed
Respond to error prompts
login successful
Redirect to homepage
3. Username login interface definition
Receive parameters
Verification parameters
Determine whether the parameter is available
Is the format of the phone number correct?
Judge business logic processing
Check whether the mobile phone number exists from the database
verify password
Save state
return
# lghome/api_1_0/passport.py
@api.route("/sessions", methods=["POST"])
def login():
"""
用户登录
:param: 手机号,密码
:return: json
"""
# 接收参数
request_dict = request.get_json()
mobile = request_dict.get('mobile')
password = request_dict.get('password')
print(mobile,password)
# 校验参数
if not all([mobile, password]):
return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
# 判断手机号格式
if not re.match(r'1[345678]\d{9}', mobile):
return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')
# 判断业务逻辑处理
# 从数据库查询手机号是否存在
try:
user = User.query.filter_by(mobile=mobile).first()
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR, errmsg='获取信息失败')
# 验证密码
if user is None or not user.check_pwd_hash(password):
return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')
# 保存登录状态
session['name'] = user.name
session['mobile'] = user.mobile
session['user_id'] = user.id
# 返回
return jsonify(errno=RET.OK, errmsg='登录成功')
4. Algorithm optimization
4.1 Limit the number of errors
If the number of errors is not limited, the account password will be maliciously tested
Limit the number of errors within a certain period of time, after exceeding the limit, login is not allowed
After receiving the parameters, first determine whether the front-end IP is out of limit
Get the number of times that the IP has been accessed incorrectly from redis
When the number of errors is not empty and is greater than or equal to the limit, an error will be returned directly
Determine whether the mobile phone number exists (whether it is a registered user) and whether the password is incorrect,
If there is an error, the number of errors is increased by 1 and stored in redis, plus the effective time
# 判断业务逻辑处理
# 判断错误次数是否超过限制,如果超过限制直接返回
# redis 用户IP地址:次数
user_ip = request.remote_addr
print(user_ip)
try:
access_nums=redis_store.get("access_nums_%s"%user_ip)
print("access_nums_%s"%user_ip,access_nums)
except Exception as e:
logging.error(e)
else:
if access_nums is not None and int(access_nums)>=constants.LOGIN_ERROR_MAX_TIMES:
return jsonify(errno=RET.REQERR, errmsg='错误次数太多,请稍后重试')
# 验证密码
# if user is None or not user.check_pwd_hash(password):
# return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')
if user is None or not user.check_pwd_hash(password):
try:
redis_store.incr("access_nums_%s" % user_ip)
redis_store.repire("access_nums_%s"%user_ip,constants.LOGIN_ERROR_FORBID_TIME)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')
4.2 Use pipeline when saving error times
# 验证密码# if user is None or not user.check_pwd_hash(password):# return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')if user is None or not user.check_pwd_hash(password):
try:
# redis管道
pl = redis_store.pipeline()
pl.incr("access_nums_%s" % user_ip)
pl.repire("access_nums_%s"%user_ip,constants.LOGIN_ERROR_FORBID_TIME)
pl.execute()
except Exception as e:
logging.error(e)return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')
Two, check login
After the user logs in, when the page is refreshed, the login status needs to be judged
Some pages can only be used in the login state, and the login state needs to be judged
1. Interface design
1.1 Request method
Options
Program
Request method
GET
Request address
/sessions
1.2 Request parameters: none
1.3 Response result: json
first name
Types of
Do you have to
Description
errno
String
Yes
error code
errmsg
String
Yes
Error content
data
dictionary
no
{"Name": Login name}
2. Login check interface definition
Read session user information
If it exists, it means the user is logged in, otherwise it is not logged in
Return the corresponding result
def check_login():
"""
检查登录状态
:return: 用户的信息或者返回错误信息
"""
name = session.get('name')if name is not None:
return jsonify(errno=RET.OK, errmsg='true', data={
"name": name})
else:
return jsonify(errno=RET.SESSIONERR, errmsg='false')