React低代码项目:用户登陆

news/2025/2/27 7:29:16

吐司问卷:用户登陆

Date: February 17, 2025 4:12 PM (GMT+8)


JWT

**概念:**登陆成功后,服务端返回一个 token

JWT组成:

JWT 由三个部分组成:头部(Header)载荷(Payload)签名(Signature)。它们通过点(.)连接,格式如下:

header.payload.signature

示例:

假设用户登录成功,后端生成了一个 JWT,格式如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

这个 JWT 分为三部分:

  1. 头部(Header)eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
  2. 载荷(Payload)eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
  3. 签名(Signature)SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT 工作流程通常如下:

  1. 用户登录: 用户提供用户名和密码,后端验证身份。
  2. 生成 JWT: 登录成功后,后端生成 JWT,包含用户身份信息,并通过密钥签名,确保其不可篡改。
  3. 返回 JWT: 后端将 JWT 发送给客户端,客户端通常将 JWT 存储在浏览器的 LocalStorage 或 Cookie 中。
  4. 客户端请求: 客户端在后续请求中将 JWT 作为 Authorization 头传递给后端(通常是 Authorization: Bearer <token>)。
  5. 服务器验证 JWT: 服务器根据 JWT 中的签名和密钥验证 JWT 的合法性,如果合法,则执行相应的操作,否则返回错误信息。



开发用户的 mock 和 service

思路:

  • 封装 axios 请求拦截器:增加用户token
  • 设计 用户注册登陆接口
  • 设计 工具函数 user-token:用于管理用户 token
  • 设计 问卷页面 的当前用户显示与退出功能

封装 axios 请求拦截器:增加用户token

ajax.ts

import axios from 'axios'
import { message } from 'antd'
import { getToken } from '../utils/user-token'

const instance = axios.create({
  timeout: 10000,
})

instance.interceptors.request.use(
  config => {
    const token = getToken()
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

instance.interceptors.response.use(res => {
  const resData = (res.data || {}) as ResType
  console.log('resData', resData)
  const { errno, data, msg } = resData
  if (errno !== 0) {
    if (msg) {
      message.error(msg)
    }
    throw new Error(msg || '未知错误')
  }
  return data as any
})

export default instance

export type ResType = {
  errno: number
  data?: ResDataType
  msg?: string
}

// key表示字段名,any表示字段值的类型
export type ResDataType = {
  [key: string]: any
}

设计 用户注册登陆接口:

user.ts

import axios, { ResDataType } from './ajax'

// 获取用户信息
export async function getUserInfoService(): Promise<ResDataType> {
  const url = '/api/user/info'
  const data = (await axios.get(url)) as ResDataType
  return data
}

// 注册用户
export async function registerService(
  username: string,
  password: string,
  nickname?: string
): Promise<ResDataType> {
  const url = '/api/user/register'
  const body = {
    username,
    password,
    nickname: nickname || username,
  }
  const data = (await axios.post(url, body)) as ResDataType
  return data
}

// 登陆用户
export async function loginService(
  username: string,
  password: string
): Promise<ResDataType> {
  // Updated return type
  const url = '/api/user/login'
  const body = {
    username,
    password,
  }
  const data = (await axios.post(url, body)) as ResDataType
  return data
}

设计工具函数 user-token:用于管理用户 token:

user-token.ts

/**
 * @description 管理用户token
 */

const KEY = 'USER_TOKEN'

export function setToken(token: string) {
  localStorage.setItem(KEY, token)
}

export function getToken() {
  return localStorage.getItem(KEY) || ''
}
export function removeToken() {
  localStorage.removeItem(KEY)
}

设计 问卷页面 的当前用户显示与退出功能:

userInfo.tsx

image.png

import React, { FC } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { LOGIN_PATHNAME } from '../router'
import { Button, message } from 'antd'
import { UserOutlined } from '@ant-design/icons'
import { getUserInfoService } from '../services/user'
import { removeToken } from '../utils/user-token'
import { useRequest } from 'ahooks'

const UserInfo: FC = () => {
  const nav = useNavigate()
  const { data } = useRequest(getUserInfoService)
  const { username, nickname } = data || {}
  const logout = () => {
    removeToken()
    message.success('退出成功')
    nav(LOGIN_PATHNAME)
  }
  const UserInfo = () => {
    return (
      <>
        <span style={{ color: '#e8e8e8' }}>
          <UserOutlined />
          {nickname || username}
        </span>
        <Button type="link" onClick={logout}>
          退出
        </Button>
      </>
    )
  }
  const Login = () => {
    return (
      <>
        <Link to={LOGIN_PATHNAME}>登陆</Link>
      </>
    )
  }
  return <div>{username ? <UserInfo /> : <Login />}</div>
}

export default UserInfo


http://www.niftyadmin.cn/n/5869724.html

相关文章

Selenium 调用模型接口实现功能测试

要使用 Selenium 调用模型接口实现功能测试,可按以下步骤进行: 1. 环境准备 安装 Selenium:使用 pip install selenium 安装 Selenium 库。安装浏览器驱动:根据使用的浏览器(如 Chrome、Firefox 等)下载对应的驱动,并将其添加到系统的环境变量中。例如,Chrome 浏览器需…

【Jenkins】一种灵活定义多个执行label节点的jenkinsfile写法

确定执行机器和自定义工作目录&#xff08;忽略节点的workspace&#xff09; pipeline{agent {node {label "XXXXX"customWorkspace "E:/workspace/"}}parameters {}options {}stages {}post {} }仅确定执行机器 pipeline{agent { label "XXXXX&quo…

CSDN年度评选揭晓,永洪科技AI技术与智能应用双星闪耀

近日&#xff0c;永洪科技在CSDN&#xff08;中国专业开发者社区&#xff09;的年度评选中&#xff0c;凭借在人工智能技术创新与vividime在行业应用中的卓越表现&#xff0c;一举斩获“人工智能企业”及“智能应用”双料大奖。这一荣誉不仅彰显了永洪科技在AI领域的领先地位&a…

ExpMoveFreeHandles函数分析和备用空闲表的关系

第一部分&#xff1a;ExpMoveFreeHandles和备用空闲表的关系 ULONG ExpMoveFreeHandles ( IN PHANDLE_TABLE HandleTable ) { ULONG OldValue, NewValue; ULONG Index, OldIndex, NewIndex, FreeSize; PHANDLE_TABLE_ENTRY Entry, FirstEntry; EXHAND…

计算机网路:自顶向下方法——第三章 运输层

本博客是通过学习中国科大郑烇老师的计算机网络课程所写的笔记 网络层实现主机之间的逻辑通信&#xff0c;而传输层实现不同主机的进程之间的逻辑通信 传输层不提供保证时延、保证带宽的服务 一、多路复用与多路分解 将主机之间的交付扩展到不同主机的进程间的交付&#xff…

使用OpenCV实现帧间变化检测:基于轮廓的动态区域标注

在计算机视觉中&#xff0c;帧间差异检测&#xff08;frame differencing&#xff09;是一种常用的技术&#xff0c;用于检测视频流中的动态变化区域。这种方法尤其适用于监控、运动分析、目标追踪等场景。在这篇博客中&#xff0c;我们将通过分析一个基于OpenCV的简单帧间差异…

【Java学习】Object类与接口

面向对象系列五 一、引用 1.自调传自与this类型 2.类变量引用 3.重写时的发生 二、Object类 1.toString 2.equals 3.hashCode 4.clone 三、排序规则接口 1.Comparable 2.Comparator 一、引用 1.自调传自与this类型 似复刻变量调用里面的非静态方法时&#xff0c;都…

如何在开发中更好地使用DeepSeek:从入门到精通

如何在开发中更好地使用DeepSeek&#xff1a;从入门到精通 目录 引言DeepSeek简介 2.1 DeepSeek是什么&#xff1f;2.2 DeepSeek的核心功能2.3 DeepSeek的应用场景 开发环境搭建 3.1 安装DeepSeek3.2 配置开发环境3.3 常见问题及解决方案 DeepSeek基础使用 4.1 数据准备4.2 模…