1. 程式人生 > >python實現登入驗證系統(搭建MVC框架)

python實現登入驗證系統(搭建MVC框架)

小型登入註冊驗證系統

一、概述

​ 使用Redis+MySQL資料庫實現一個小型的登入註冊驗證系統。在這個系統中初步瞭解認識MVC框架

​ 具備功能:登入、註冊、改密、登出。

​ 資料庫:RedisMySQL。使用Redis把使用者資訊儲存在記憶體中,查詢資料快。MySQL儲存空間更大,對錶之間的關係管理更好。兩者結合使用發揮各自的優勢已是當下流行的資料庫使用方式。

​ 開發語言:Python

​ MVC框架:MVC全名是Model View Controller,是模型(model)-檢視(view)-控制器(controller)的縮寫,一種軟體設計典範,用一種業務邏輯、資料、介面顯示分離的方法組織程式碼,將業務邏輯聚集到一個部件裡面,在改進和個性化定製介面及使用者互動的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於對映傳統的輸入、處理和輸出功能在一個邏輯的圖形化使用者介面的結構中。

二、程式碼

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、部分功能展示

註冊:

這裡寫圖片描述

登入:

這裡寫圖片描述

改密:

這裡寫圖片描述

登出:

這裡寫圖片描述