小型登入注冊驗證系統
關注公衆号“輕松學程式設計”了解更多。
一、概述
使用Redis+MySQL資料庫實作一個小型的登入注冊驗證系統。在這個系統中初步了解認識MVC架構。
具備功能:登入、注冊、改密、登出。
資料庫:Redis,MySQL。使用Redis把使用者資訊存儲在記憶體中,查詢資料快。MySQL存儲空間更大,對表之間的關系管理更好。兩者結合使用發揮各自的優勢已是當下流行的資料庫使用方式。
開發語言:Python。
MVC架構:MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟體設計典範,用一種業務邏輯、資料、界面顯示分離的方法組織代碼,将業務邏輯聚集到一個部件裡面,在改進和個性化定制界面及使用者互動的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用于映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化使用者界面的結構中。
二、代碼
雲盤:源碼連結:https://pan.baidu.com/s/184igcfqY6JcaA5oR_7Ypbg 密碼:rja6
GitHub:https://github.com/liangdongchang/pyCheckLoginSys.git
1、Init
用來初始化服務:
1、在mysql上建立一個資料庫“homework”和建表"t_usr"
2、開啟redis服務程式
'''
@author ldc
'''
import os
import pymysql
'''
初始化服務:
1、在mysql上建立一個資料庫“homework”和建表"t_usr"
2、開啟redis服務程式
'''
# 建立資料庫連接配接
conn = pymysql.connect(
host='localhost',
user='root',
password="123456",
port=3306
)
# 擷取遊标
cursor = conn.cursor()
# 建立資料庫
dbname = 'homework'
sql='''
create database if not EXISTS %s charset=utf8;
'''%dbname
cursor.execute(sql)
# 使用資料庫
cursor.execute('use %s'%dbname)
# 建立表
sql = '''
create table if not EXISTS t_usr(
id INTEGER PRIMARY KEY auto_increment,
username varchar(20) unique not null,
password varchar(20) not null
);
'''
cursor.execute(sql)
# 關閉遊标與連接配接
cursor.close()
conn.close()
# 開啟redis服務,建立一個啟動redisd.bat檔案,
#以後開啟redis服務就可以直接打開這個檔案了
def openRedisd(path):
rPath = """@echo off
redis-server %s
pause"""%path
with open(r"C:\Users\LDCPC\Desktop\啟動redisd.bat","w",encoding="ANSI")
as f:
f.write(rPath)
openRedisd(r"D:\ruanjian\redis-64.2.8.2101\redis.windows.conf")
# 打開檔案“啟動redisd.bat”
os.popen(r"C:\Users\LDCPC\Desktop\啟動redisd.bat")
2、View層
用來與使用者互動:接收使用者的輸入和顯示結果給使用者。
'''
@author ldc
'''
from controller import urls
from model.model import User
from utils.dbUtil import RedisUtil
'''
需求:登入注冊驗證
1、登入
2、注冊
3、改密
4、登出
'''
# 主界面接口
def index():
while True:
#登入界面
print("********************************")
print("* *")
print("* (1) 登入 (2)注冊 *")
print("* (3) 改密 (4)登出 *")
print("* (5)退出 *")
print("********************************")
print()
num = input("請輸入功能序号:")
if num in ['1','2','3','4','5']:
return num
else:
print("輸入有誤,請重新輸入!!!")
# 輸入賬号與密碼
def inputInfo():
return input("請輸入賬号和密碼(逗号隔開):").split(',')
if __name__ == '__main__':
# 連接配接redis資料庫
RedisUtil.connect()
while True:
# 初始化界面
num = index()
# 輸入賬号密碼
username, password = inputInfo()
# 執行個體化一個使用者類
user = User(username, password)
if num == '1':
urls.login(user) #登入
elif num == '2':
urls.regist(user) # 注冊
elif num == '3':
urls.changePasswd(user) # 改密
elif num == '4':
urls.deleteUser(user) # 登出
else:
break
3、Controller層
實作業務邏輯,控制整個系統的實作流程。
'''
@author ldc
'''
from model.model import UserDao
# 先查詢該使用者是否存在資料庫中
def exists(user):
'''先檢視Redis緩存中是否有該使用者資料'''
if not UserDao.exists(user.username, 'redis'):
'''然後在mysql中查詢該使用者是否存在'''
if UserDao.exists(user.username, 'mysql'):
# 若在mysql存在就把該使用者寫進redis,
UserDao.redis.set(user.username, user.password)
return 'mysql'
else :
return None
return 'redis'
'''
# 登入子產品
先在redis上驗證,驗證成功則提示在redis上驗證成功
否則到mysql中驗證,驗證成功則提示在mysql上驗證成功
否則提示使用者不存在
'''
def login(user):
print("------------登入界面------------")
# 查詢該使用者資訊是否存在資料庫中
whereDB = exists(user)
if whereDB == 'redis':
# 比對密碼是否正确
if UserDao.query(user, 'redis') == user.password:
print("[在redis中查詢到該使用者]登入成功!!!")
return 1
else:
print("[在redis中查詢到該使用者] 登入失敗,使用者名或者密碼不正确!!!")
elif whereDB == 'mysql':
# 比對密碼是否正确
if UserDao.query(user, 'mysql'):
print("[在mysql中查詢到該使用者] 登入成功!!!")
return 1
else:
print("[在mysql中查詢到該使用者] 登入失敗,使用者或者密碼不正确!!!")
else:
print("[在mysql中查詢不到該使用者]登入失敗,該使用者不存在,請注冊後再登入!!!")
return 0
'''
# 注冊子產品
先在redis上查詢賬号是否存在,存在則注冊失敗
否則到mysql上查詢,使用者存在則注冊失敗
否則注冊成功,把賬号寫進mysql,寫進redis
'''
def regist(user):
print("------------注冊界面------------")
# 查詢該使用者資訊是否存在資料庫中
whereDB = exists(user)
if whereDB :
print("注冊失敗,該使用者已存在!!!")
else:
if UserDao.insert(user):
print("注冊成功!!!")
else:
print("注冊失敗!!!")
'''
# 修改密碼子產品
先在redis上和mysql上查詢,使用者存在就在mysql上修改該使用者密碼,
然後把該使用者資訊重新寫進redis中
在mysql中查詢不到該使用者,就傳回該使用者不存在,改密失敗
'''
def changePasswd(user):
print("------------改密界面------------")
# 查詢該使用者資訊是否存在資料庫中
whereDB = exists(user)
if whereDB:
user.password = input("請輸入新密碼:")
if UserDao.changePasswd(user):
print("改密成功!!!")
else:
print("改密失敗!!!")
else:
print("使用者不存在,改密失敗!!!")
'''
# 登出使用者子產品
先在在redis上和mysql上查詢,使用者存在就在mysql和redis上删除該使用者
在mysql中查詢不到該使用者,就傳回該使用者不存在,登出失敗
'''
def deleteUser(user):
print("------------登出界面------------")
# 查詢該使用者資訊是否存在資料庫中
if login(user):
if UserDao.deleteUser(user):
print("登出成功!!!")
return
print("登出失敗!!!")
4、Model層
用來通路資料庫,實作業務邏輯與資料庫分離,易于維護系統。
'''
@author ldc
'''
from utils.dbUtil import RedisUtil, MySQLUtil
# 使用者模型類
class User:
def __init__(self,username,password):
self.username = username
self.password = password
# UserDao
# 封裝了對User資料的增删改查
# Dao=Database Access Object 資料庫通路對象
class UserDao:
# 建立資料庫對象
redis = RedisUtil()
mySQL = MySQLUtil('homework','t_usr')
# 執行資料庫查詢操作,傳回查詢結果
@classmethod
def query(cls,user,dbType):
dataDict = {}
dataDict["username"] = user.username
dataDict["password"] = user.password
if dbType == 'redis':
return cls.redis.get(user.username)
elif dbType == 'mysql':
return cls.mySQL.query(dataDict)
# 執行資料庫查詢操作,查詢使用者是否存在,傳回查詢結果
@classmethod
def exists(cls,username,dbType):
dataDict = {}
dataDict["username"] = username
if dbType == 'redis':
return cls.redis.exists(username)
elif dbType == 'mysql':
return cls.mySQL.exists(dataDict)
else:
pass
# 執行資料插入操作,先把使用者資訊添加進mysql,然後再添加進redis
@classmethod
def insert(cls, user):
dataDict = {}
dataDict["username"] = user.username
dataDict["password"] = user.password
if cls.mySQL.insert(dataDict):
cls.redis.set(user.username,user.password)
return 1
else:
print("注冊失敗,伺服器繁忙!!!")
return 0
# 修改密碼
@classmethod
def changePasswd(cls, user):
dataDict = {'changeCol': 'password = %s'%user.password,
'caluse' : 'username = %s'%user.username}
if cls.mySQL.update(dataDict):
cls.redis.set(user.username,user.password)
return 1
else:
print("修改密碼失敗,伺服器繁忙!!!")
return 0
# 登出使用者
@classmethod
def deleteUser(cls, user):
dataDict = {'username' : user.username}
if cls.mySQL.delete(dataDict):
cls.redis.delete(user.username)
return 1
else:
print("修改密碼失敗,伺服器繁忙!!!")
return 0
5、Utils工具包
用來實作資料庫的增删改查,可以被不同的系統調用。
'''
@author ldc
'''
import pymysql
import redis as redis
'''
MySQL增删改查操作類
'''
class MySQLUtil:
def __init__(self,dbName,tableName):
self.dbName = dbName
self.tableName = tableName
# 連接配接資料庫,并生成全局可用的連接配接對象和查詢遊标
def connect(self):
self.conn = pymysql.connect(
host='localhost', user='root', password="123456",
database=self.dbName, port=3306,
)
self.cursor = self.conn.cursor()
# 關閉全局遊标,斷開全局連接配接
def disconnect(self):
self.cursor.close()
self.conn.close()
# 查詢使用者名是否存在
def exists(self,dataDict):
caluse = ''
for key,value in dataDict.items():
caluse += key + '="'+ value + '"'
# print(caluse)
sql = """
select * from %s where %s ;
""" % (self.tableName, caluse)
return self.execute(sql)
# 驗證使用者名和密碼是否正确
def query(self, dataDict):
# 查詢子條件拼接
caluse = ''
for key, value in dataDict.items():
caluse += key + '="' + value + '" and '
caluse = caluse[:-4]
# print(caluse)
sql = """
select * from %s where %s;
"""% (self.tableName, caluse)
return self.execute(sql)
# 添加新使用者
def insert(self, dataDict):
# sql語句拼接
columns = ''
values = ''
for key, value in dataDict.items():
columns += key + ','
values += '"' + value + '",'
columns = columns[:-1]
values = values[:-1]
sql = """
insert into %s (%s) VALUES (%s);
""" % (self.tableName, columns,values)
# print(sql)
return self.execute(sql)
# 更新
def update(self, dataDict):
# sql語句拼接
changeCol = dataDict['changeCol'] #要改變值的列名
caluse = dataDict['caluse'] #要改變值的子條件
sql = 'update %s set %s where %s'%(self.tableName,changeCol,caluse)
return self.execute(sql)
# 删除
def delete(self, dataDict):
# sql語句拼接
caluse = ''
for key,value in dataDict.items():
caluse += key + '="' + value + '"'
sql = """
delete from %s where %s;
""" % (self.tableName,caluse)
# print(sql)
return self.execute(sql)
# print(sql)
# 執行sql語句
def execute(self, sql):
self.connect()
affected = 0
try:
affected = self.cursor.execute(sql)
except BaseException as e:
print(e)
affected = 0
finally:
self.conn.commit()
self.disconnect()
return affected
'''
redis增删改查操作類
'''
class RedisUtil:
# redis連接配接
@classmethod
def connect(cls):
cls.client = redis.Redis(
host='localhost', port=6379,
db=1, password='123456',
)
# 判斷鍵是否存在
@classmethod
def exists(cls,key):
return cls.client.exists(key)
# 存儲鍵值,
@classmethod
def set(cls,key,value):
# 鍵值存儲在緩存中,保留時間為30秒
cls.client.setex(key,value,30)
# 擷取鍵值
@classmethod
def get(cls,key):
res = cls.client.get(key).decode("utf-8")
return res
# 删除鍵值
def delete(cls, key):
cls.client.delete(key)
6、部分功能展示
注冊:
登入:
改密:
登出:
後記
【後記】為了讓大家能夠輕松學程式設計,我建立了一個公衆号【輕松學程式設計】,裡面有讓你快速學會程式設計的文章,當然也有一些幹貨提高你的程式設計水準,也有一些程式設計項目适合做一些課程設計等課題。
也可加我微信【1257309054】,拉你進群,大家一起交流學習。
如果文章對您有幫助,請我喝杯咖啡吧!
公衆号
關注我,我們一起成長~~