使用Qwik/Prisma 构建管理后台二: 处理登录与认证

131 阅读2分钟

因为很忙,InfyniDock也不太需要用户系统, 所以我其实并没有真正的花时间去写用户系统,但是在做一个后台管理系统的时候,没有用户密码来登录又不太现实.

所以我只是简单的模拟一下,在后台手写一个用户名与密码,简单认证,前台发送固定的用户名密码到后端去认证.

现在看一下,Qwik是怎么处理前端cookie的.

第一步,处理Qwik的onRequest函数:

src/routes/layouts.tsx (必须写在这个文件里)

export const onRequest: RequestHandler = async ({next, sharedMap, cookie,redirect,url }) => {
  const user = loadUserFromCookie(cookie);
  // 如果当前是login页面,不做处理,正常渲染页面
  if (url.pathname === '/login/'){
    await next();
    return 
  }
  
  // 其它页面,如果没有用户登录信息,则重定向到登录页面
  if ( !user ) {
    throw redirect(308, '/login')
  }
 
  sharedMap.set('user', user as User)

  await next();
};

从cookie里处理数据

function loadUserFromCookie(cookie: Cookie): User | null {
  const username = cookie.get('username')?.value;
  if (username) {
    return {
      username: username,
      email: `infyniclick@gmail.com`,
    };
  } else {
    return null;
  }
}

处理完以上的基础部分之后,我们来写一个简单的登录页面看看:

routes/login/index.tsx

import { component$, $, useStore } from "@builder.io/qwik"
import { server$, useNavigate } from "@builder.io/qwik-city"

const requestLogin = server$(async function (
  username: string,
  password: string
) {
  if (password) {
    this.cookie.delete("username")
    this.cookie.delete("user")
    this.cookie.set("username", username, { path: "/" })
    this.cookie.set("user", { username: username }, { path: "/" })
    this.sharedMap.set("user", { username: username })
    return true
  }

  return false
})

export default component$(() => {
  // 前端状态
  const store = useStore({ username: "test", password: "123456" })
  const nav = useNavigate()
  
  // 点击登录按钮之后的处理函数
  const login$ = $(async () => {
    // 调用服务端接口,处理登录后续事件
    const result = await requestLogin(store.username, store.password)
    if (result) {
      await nav("/dashboard/")
    }
  })

  return (
    <>
      <div>login in page</div>
      <button onClick$={async () => await login$()}> login </button>
    </>
  )
})

20240205182550.jpg

点击一下login, 看看后端是不是真正的接收到了用户名和密码:

20240205182905.jpg

通过以上的简单的代码,就实现了前后端的登录认证通讯.

最后, 普及Qwik的一些知识点:

一、server$

是在服务器端执行的代码,你可以看到它的console.log是在后端进行输出,不是在浏览器输出;像我们上面的例子,就可以在requestLogin里,查询数据库,并校验密码与用户名,再返回给前端. 以后再用prisma来查询数据库.

二、useVisibleTask$

是在浏览器端执行的代码,如果你需要明确的在浏览器端处理的UI任务,就需要放在useVisibleTask$里处理.

三、sharedMap

看一下官方的解释:

Use `sharedMap` as a way to share data between middleware functions. The `sharedMap` is scoped to HTTP request. A common use case is to use `sharedMap` to store user details so that it can be used by other middleware functions, `routeLoader$()` or components.

shareMap 可以在后端写入数据,然后在routeLoader$()取出来.比如我们可以这样子取值:

src/routes/layouts.tsx (必须写在这个文件里)
export const useUser = routeLoader$(({ sharedMap }) => {
  return sharedMap.get('user') as User;
});

然后就可以显示出来:

import { component$ } from "@builder.io/qwik"
import type { DocumentHead } from "@builder.io/qwik-city"
import { useUser } from "./layout"

export default component$(() => {
  const log = useUser()
  return (
    <>
      <h1>
        Hi 👋 {log.value.username} {log.value.email}
      </h1>
      <p>
        Can't wait to see what you build with qwik!
        <br />
        Happy coding.
      </p>
    </>
  )
})

20240205200141.jpg

暂时先这样.下一章写查询数据