
使用NestJS和Prisma構建REST API:身份驗證
主要使用了axios發了post請求,FastAPI部分是接收json格式,在請求里加了header,這個項目啟動的端口是8080,FastAPI的后端端口是4321,涉及到一個跨域問題,又在請求里加了{ withCredentials: true }
,頁面登錄部分,代碼只修改了這些。
router的index.js里加一個dashboard的跳轉:
{
path: '/Dashboard',
//name: 'Register',
component: () => import("../views/Dashboard.vue")
},
在view下創建一個Dashboard的空白頁面。
<template>
<div class="about">
<h1>This is Dashboard</h1>
</div>
</template>
在以前的項目時,已經安裝好本地MySQL數據庫,為了這個演示,用python只建立一個數據庫和表,
import mysql.connector
# 數據庫連接配置
db_config = {
'host': 'localhost',
'user': 'root',
'password': '123456'
}
# 初始化 MySQL 連接
def get_db_connection():
return mysql.connector.connect(**db_config)
# 創建數據庫和表
def create_database_and_table():
conn = get_db_connection()
cursor = conn.cursor()
# 創建數據庫
cursor.execute("CREATE DATABASE IF NOT EXISTS vue_blog")
# 切換到指定數據庫
cursor.execute("USE vue_blog")
# 創建用戶信息表
cursor.execute("""
CREATE TABLE IF NOT EXISTS user_info (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
nickname VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL
)
""")
cursor.close()
conn.close()
# 查詢用戶
def query_user(username: str, password: str):
conn = get_db_connection()
cursor = conn.cursor()
# 切換到指定數據庫
cursor.execute("USE vue_blog")
# 查詢數據庫中是否存在該用戶
query = "SELECT * FROM user_info WHERE username = %s"
cursor.execute(query, (username,))
user = cursor.fetchone()
print(user)
if user:
# 如果找到了用戶,則比對密碼
if user[3] == password: # 第4列是密碼字段
print("用戶名和密碼匹配")
else:
print("密碼不匹配")
else:
print("用戶不存在")
cursor.close()
conn.close()
if __name__ == "__main__":
#create_database_and_table()
query_user("gaofeng", "123456")
連接到本地數據庫,創建一個新庫和一個表,用于存儲用戶名信息。
手動填加一個用戶信息,用于驗證信息,進行登錄。
編寫這個后端只提供登錄驗證,一個Post請求,拿著用戶名和密碼去驗證對比,這里不涉及用戶名和密碼的加解,都是明文的。
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
import mysql.connector
from fastapi.middleware.cors import CORSMiddleware
# 允許所有來源的跨域請求
# 數據庫連接配置
db_config = {
'host': 'localhost',
'user': 'root',
'password': '123456',
'database': 'vue_blog'
}
# 初始化 FastAPI 應用
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:8080"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
)
# 定義請求體模型
class User(BaseModel):
username: str
password: str
# 初始化 MySQL 連接
def get_db_connection():
return mysql.connector.connect(**db_config)
# 根據用戶名和密碼驗證用戶
def verify_user(username: str, password: str):
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("USE vue_blog")
# 查詢數據庫中是否存在該用戶
query = "SELECT * FROM user_info WHERE username = %s AND password = %s"
cursor.execute(query, (username, password))
user = cursor.fetchone()
cursor.close()
conn.close()
return user
# 定義 POST 路由,接收用戶名和密碼進行驗證
@app.post("/login")
def login(user: User):
# 驗證用戶
print(user)
result = verify_user(user.username, user.password)
print(result)
if result:
return {"message": "Login successful"}
else:
print(result)
raise HTTPException(status_code=401, detail="Unauthorized")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=4321)
下面代碼是后加的,項目運行端口是8080,后端端口是4321,不做設置會報錯,加上下面這些設置,就能正常訪問了。
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:8080"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
)
每次啟動項目時,可能端口號會變,端口位置可以設置成*。
后端運行fastapi這個腳本,前端啟動項目,
fastapi關于這個Login的說明。
輸入用戶名,密碼登錄,登錄成功。
用戶登錄之后,頁面來回切換,需要有個狀態管理,就會用到一個Pinia組件。這里主要參考鄧瑞編程和吳悠講編程的pinia內容。這兩個視頻都是在b站。
安裝pinia:
npm install pinia
在package.json中,顯示pinia的版本是2.1.7。修改main.js,引入pinia。
import { createPinia } from 'pinia'
const pinia = createPinia()
//createApp(App).use(store).use(router).mount('#app')
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(store)
app.use(router)
app.use(ElementPlus)
app.use(pinia)
app.provide('$axios',axios)
app.mount('#app')
import { defineStore } from 'pinia';
import {ref, reactive} from 'vue';
export const useWebStore = defineStore('web',() => {
const user = reactive({
isLoggedIn: false,
userName: null,
})
const login= (userInfo) => {
user.isLoggedIn = true,
user.userInfo = userInfo
console.log(user.userInfo)
}
const logout= () => {
user.isLoggedIn = false,
user.userInfo = null
}
return {
user,
login,
logout
}
})
在Login.vue中修改,引入web.js:
import { useWebStore } from '../store/web'
const userStore = useWebStore()
修改登錄成功,跳轉前增加登錄信息修改:
const Login = reactive({
loginName: '',
password: '',
})
const onSubmit = () => {
const user = {
username: Login.loginName,
password: Login.password
}
console.log(userStore.user.isLoggedIn)
axios.post('http://localhost:4321/login', {
username: Login.loginName,
password: Login.password
},{
headers: {
'Content-Type': 'application/json'
}},
{ withCredentials: true }
)
.then(response => {
console.log(Login)
const { data } = response
if (data.message === 'Login successful') {
//router.push('/dashboard')
ElMessage({
message: '恭喜,登錄成功!',
type: 'success',
})
userStore.login(Login.loginName)
console.log(userStore.user.isLoggedIn)
router.push('/dashboard')
} else {
ElMessage({
message: '登錄失敗,請檢查用戶名和密碼!',
type: 'error',
})
}
})
.catch(error => {
console.error('登錄請求錯誤:', error)
ElMessage({
message: '登錄請求出錯,請稍后重試!',
type: 'error',
})
})
}
登錄前后打印登錄狀態。
安裝pinia的持久化插件,把pinia的存儲到本地localStorage中:
npm i pinia-plugin-persistedstate
//從 pinia-plugin-persistedstate 模塊中導入 piniaPluginPersistedstate
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
//將插件添加到 pinia 實例上
pinia.use(piniaPluginPersistedstate)
在上面的web.js中填加一個參數,填加一個{persist:true}:
import { defineStore } from 'pinia';
import {ref, reactive} from 'vue';
export const useWebStore = defineStore('web',() => {
const user = reactive({
isLoggedIn: false,
userName: null,
})
const login= (userInfo) => {
user.isLoggedIn = true,
user.userInfo = userInfo
console.log(user.userInfo)
}
const logout= () => {
user.isLoggedIn = false,
user.userInfo = null
}
return {
user,
login,
logout
}
},
{ persist:true
})
再次登錄成功后,在控制臺,應用程序的LocaStorage中,可以看到
再次登錄時,登錄前和登錄后,
說明他的登錄狀態是保持的,有了這個插件,他會自動讀取信息,無需手動操作。
上面項目代碼都比較簡單,如果需要,后臺回復『0415』獲取所有代碼和資源。
本文章轉載微信公眾號@峰哥Python筆記