diff --git a/README.md b/README.md index 51aeada..8cf1992 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # 接下来的计划 -- 用户密码哈希存储 -- 文章表增加对最后编辑时间的支持与对加密的支持 +- 用户密码哈希存储(👌) +- 文章表增加对最后编辑时间的支持与对加密的支持(没啥用感觉) - 美化markdown的渲染 (👌) - 迁移仓库到gitea (👌) \ No newline at end of file diff --git a/hooks/useMiaoFetch.ts b/hooks/useMiaoFetch.ts index 3d4514e..d69bcfa 100644 --- a/hooks/useMiaoFetch.ts +++ b/hooks/useMiaoFetch.ts @@ -56,6 +56,15 @@ export default function useFetch() { 'Authorization': `Bearer ${userStore.token}` } }), + deletePost: (id: number) => $fetch('/api/posts/deletePost', { + body: { + id + }, + method: 'POST', + headers: { + 'Authorization': `Bearer ${userStore.token}` + } + }) }, user: { login: (body: { diff --git a/pages/user/main/post/edit-[id].vue b/pages/user/main/post/edit-[id].vue index b212d8c..4d6fa4a 100644 --- a/pages/user/main/post/edit-[id].vue +++ b/pages/user/main/post/edit-[id].vue @@ -39,7 +39,7 @@ type resType = { } & postItem -const { post: { getPost, updatePost, uploadPost } } = useFetch() +const { post: { getPost, updatePost, uploadPost, deletePost } } = useFetch() const route = useRoute() const router = useRouter() @@ -86,12 +86,7 @@ const handleClickDelete = async () => { } ) try { - const response = await $fetch('/api/posts/deletePost', { - method: 'POST', - body: { - id: id.value - } - }) + const response = await deletePost(id.value) ElMessage({ type: 'success', message: '删除文章完成', @@ -99,7 +94,8 @@ const handleClickDelete = async () => { const store = useDefaultStore() store.deleteCache('posts') router.back() - } catch { + } catch(e) { + console.error(e) ElMessage({ type: 'error', message: '删除失败', diff --git a/server/api/user/login.ts b/server/api/user/login.ts index 7dea17a..f99035e 100644 --- a/server/api/user/login.ts +++ b/server/api/user/login.ts @@ -1,4 +1,3 @@ -// import { defineEventHandler, readBody, createError } from 'h3'; import bcrypt from 'bcryptjs'; import BetterSqlite3 from 'better-sqlite3'; @@ -10,9 +9,10 @@ export default defineEventHandler(async (event) => { // 查询用户 const userDB = BetterSqlite3('./userData/db/user.db'); const user: any = userDB.prepare('SELECT * FROM user WHERE username = ?').get(username); - if (!user || password !== user.password) { + const authRes = await authUser(username, password); + if(!authRes){ userDB.close(); - throw createError({ statusCode: 401, statusMessage: 'Invalid username or password' }); + throw createError({ statusCode: 401, statusMessage: 'Username or password is incorrect' }); } // 更新最后登录时间 diff --git a/server/api/user/refreshToken.ts b/server/api/user/refreshToken.ts index 34b61c0..ce9263d 100644 --- a/server/api/user/refreshToken.ts +++ b/server/api/user/refreshToken.ts @@ -10,6 +10,10 @@ export default defineEventHandler(async (event) => { try { // 验证旧的 Token const decoded = jwt.verify(token, jwtSecret) as any; + const authRes = await authUser(decoded.username, decoded.password); + if (!authRes) { + throw createError({ statusCode: 401, statusMessage: 'Username or password is incorrect' }); + } // 生成新的 Token const newToken = jwt.sign({ username: decoded.username, @@ -21,4 +25,4 @@ export default defineEventHandler(async (event) => { } catch (err) { throw createError({ statusCode: 401, statusMessage: 'Token invalid or expired', data: { err, token } }); } -}); \ No newline at end of file +}); diff --git a/server/api/user/register.ts b/server/api/user/register.ts index 15b15b7..1686719 100644 --- a/server/api/user/register.ts +++ b/server/api/user/register.ts @@ -20,10 +20,7 @@ export default defineEventHandler(async (event) => { // throw createError({ statusCode: 400, statusMessage: 'Username already exists' }); // } - // 哈希密码,暂未实现,未来实现 - // const salt = getKey().substring(0, 10); - // const hashedPassword = bcrypt.hashSync(password, salt); - const hashedPassword = password + const hashedPassword = bcrypt.hashSync(password, 10); // 插入新用户 const createTime = Date.now(); diff --git a/server/api/user/updatePassword.ts b/server/api/user/updatePassword.ts index 861bffc..153fa0d 100644 --- a/server/api/user/updatePassword.ts +++ b/server/api/user/updatePassword.ts @@ -1,4 +1,4 @@ -// import bcrypt from 'bcryptjs'; +import bcrypt from 'bcryptjs'; import BetterSqlite3 from 'better-sqlite3'; // import { defineEventHandler, createError, readBody } from 'h3'; import jwt from 'jsonwebtoken'; @@ -27,18 +27,12 @@ export default defineEventHandler(async (event) => { } // 验证旧密码是否正确 - // const passwordMatch = bcrypt.compareSync(oldPassword, user.password); - const passwordMatch = oldPassword === user.password; - if (!passwordMatch) { + const authRes = await authUser(username, oldPassword); + if (!authRes) { userDB.close(); - throw createError({ statusCode: 401, statusMessage: 'Invalid old password' }); + throw createError({ statusCode: 401, statusMessage: 'Old password is incorrect' }); } - - // 哈希新密码 - // const salt = bcrypt.genSaltSync(10); - // const hashedNewPassword = bcrypt.hashSync(newPassword, salt); - - const hashedNewPassword = newPassword; + const hashedNewPassword = bcrypt.hashSync(newPassword, 10); // 更新密码 const stmt = userDB.prepare('UPDATE user SET password =? WHERE username =?'); diff --git a/server/middleware/auth.ts b/server/middleware/auth.ts index 0258cfa..c1606aa 100644 --- a/server/middleware/auth.ts +++ b/server/middleware/auth.ts @@ -1,5 +1,4 @@ import serverConfig from "../server.config" -// import { verify } from 'jsonwebtoken' import jwt from 'jsonwebtoken' import getKey from "../utils/getKey" @@ -17,10 +16,13 @@ export default defineEventHandler(async (event) => { const token = authHeader.split('Bearer ')[1].trim() try { const decoded = jwt.verify(token, key) as { userId: number, password: string, username: string, exp: number } + const authRes = await authUser(decoded.username, decoded.password) + if (!authRes) { + throw createError({ statusCode: 401, statusMessage: 'Token invalid or expired', data: { err: 'auth failed', token } }) + } if (decoded.exp > Date.now()) { throw createError({ statusCode: 401, statusMessage: 'Token invalid or expired', data: { err: 'token expired', token } }) } - // console.log(decoded) // 将用户ID挂载到事件对象,供后续使用 // event.context.userId = decoded.userId } catch (err) { diff --git a/server/server.config.ts b/server/server.config.ts index 82249d1..cab6459 100644 --- a/server/server.config.ts +++ b/server/server.config.ts @@ -5,6 +5,7 @@ export default { '/api/test/testDir', '/api/posts/editPost', '/api/posts/uploadPost', + '/api/posts/deletePost', '/api/user/updatePassword', '/api/system/update' ]) diff --git a/server/utils/authUser.ts b/server/utils/authUser.ts new file mode 100644 index 0000000..a0f2f02 --- /dev/null +++ b/server/utils/authUser.ts @@ -0,0 +1,16 @@ +import bcrypt from 'bcryptjs'; +import BetterSqlite3 from 'better-sqlite3'; + +export default async function authUser( + username: string, + password: string +) { + const userDB = BetterSqlite3('./userData/db/user.db'); + const user: any = userDB.prepare('SELECT * FROM user WHERE username = ?').get(username); + const bPasswd = bcrypt.compareSync(password, user.password) || password === user.password; + if (!user || !bPasswd) { + userDB.close(); + return false; + } + return true; +} \ No newline at end of file