会员认证

XYGo Admin 2025-02-20 57 次阅读

会员登录注册与 JWT Token 机制

会员认证

认证体系

会员认证独立于后台管理员,使用不同的 Token Header:

对比项 后台管理员 前台会员
Token Header Authorization: Bearer Xy-User-Token
中间件 AdminAuth MemberAuth
Store useUserStore useMemberStore
路由前缀 /admin /member

登录方式

系统支持三种登录方式:

方式 适用场景 接口路径 获取方式
账号密码登录 Web 前台 POST /member/auth/login 用户名 + 密码
微信小程序登录 小程序 / 小游戏 POST /wm/auth/login 微信 code
微信公众号登录 公众号 H5 网页 GET /wm/oa/auth/url + GET /wm/oa/auth/callback OAuth2 授权

三种方式共享同一套会员体系(xy_member 表),登录后均返回 JWT Token,后续请求通过 Xy-User-Token Header 鉴权。

一、账号密码登录

复制代码
1. 用户输入账号密码
2. 前端调用 POST /member/auth/login
3. 后端校验密码(bcrypt 加密比对)
4. 生成 JWT Token
5. 返回 Token + 用户信息
6. 前端存储到 useMemberStore(持久化)
7. 后续请求自动注入 Xy-User-Token Header

二、微信小程序登录

适用于微信小程序、小游戏场景,用户无需输入账号密码,通过微信授权一键登录。

流程

复制代码
1. 小程序端调用 uni.login() 获取微信临时 code
2. 将 code 发送到 POST /wm/auth/login
3. 后端从 xy_sys_config 读取 we_mapp 分组的 appid / appsecret
4. 调用微信 jscode2session 接口,用 code 换取 openid + session_key
5. 按 platform+openid 查询 xy_member_oauth 表
6. 若用户不存在则自动注册(用户名 wx_xxx、默认昵称"微信用户")
7. 复用 token.GenerateMember 生成 JWT Token
8. 返回 {token, expiresIn, isNew}

接口定义

POST /wm/auth/login

请求参数:

json 复制代码
{
  "code": "微信登录临时code"
}

响应:

json 复制代码
{
  "code": 0,
  "data": {
    "token": "eyJhbGciOi...",
    "expiresIn": 7200,
    "isNew": true
  }
}

后台配置

在后台管理 → 系统配置 → 小程序配置中填写:

  • 微信小程序 AppID(wmapp_appid)
  • 微信小程序 AppSecret(wmapp_secret)

白名单

/wm/auth/login 已加入 MemberAuth 中间件白名单,无需携带 Token 即可访问。

三、微信公众号登录(OAuth2 网页授权)

适用于微信公众号内 H5 网页,用户在微信内打开页面后通过 OAuth2 授权登录,可获取微信昵称和头像。

前置条件

  • 需要认证的服务号(或微信测试号)
  • 在微信公众平台 → 设置与开发 → 公众号设置 → 功能设置中配置网页授权域名

流程

复制代码
1. H5 前端调用 GET /wm/oa/auth/url?redirect=前端回跳地址
2. 后端从 xy_sys_config 读取 we_oa 分组的 appid
3. 拼接微信授权 URL 并返回
4. 前端跳转到微信授权页面(window.location.href = url)
5. 用户同意授权后,微信 302 回调到 /wm/oa/auth/callback?code=xxx
6. 后端用 code 换取 access_token + openid
7. 用 access_token 调用微信 userinfo 接口获取昵称/头像
8. 按 platform+openid 查询 xy_member_oauth 表
9. 若用户不存在则自动注册(携带微信昵称和头像)
10. 复用 token.GenerateMember 生成 JWT Token
11. 返回 {token, expiresIn, isNew}

接口定义

GET /wm/oa/auth/url

请求参数:

参数 说明
redirect 授权完成后前端回跳地址

响应:

json 复制代码
{
  "code": 0,
  "data": {
    "url": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=..."
  }
}

GET /wm/oa/auth/callback

请求参数(微信回调自动携带):

参数 说明
code 微信授权码
state 防伪校验值

响应:

json 复制代码
{
  "code": 0,
  "data": {
    "token": "eyJhbGciOi...",
    "expiresIn": 7200,
    "isNew": true
  }
}

后台配置

在后台管理 → 系统配置 → 公众号配置中填写:

  • 公众号 AppID(weoa_appid)
  • 公众号 AppSecret(weoa_secret)
  • 公众号 Token(weoa_token)—— 用于消息验证

白名单

/wm/oa/auth/url/wm/oa/auth/callback 均已加入 MemberAuth 中间件白名单。

注册流程

复制代码
1. 用户填写注册信息(用户名、密码、手机号等)
2. 前端调用 POST /member/auth/register
3. 后端校验唯一性(用户名、手机号不重复)
4. 生成 salt,加密密码
5. 写入 member 表
6. 自动登录,返回 Token

数据库字段

第三方登录信息存储在独立的 xy_member_oauth 表中,与 xy_member 一对多关联:

字段 类型 说明
member_id bigint 关联 xy_member.id
platform varchar(32) 平台标识:wechat_mapp / wechat_oa / qq / alipay 等
openid varchar(128) 该平台的 openid
unionid varchar(128) unionid(可选)
session_key varchar(128) 小程序 session_key
nickname varchar(100) 该平台的昵称
avatar varchar(500) 该平台的头像
extra text 扩展 JSON

采用独立 oauth 表的好处:新增任何第三方登录只需 INSERT 一行记录,无需修改 xy_member 表结构。同一会员可绑定多个平台。

获取用户信息

登录后可通过以下接口获取当前用户信息:

GET /wm/auth/profile(需携带 Xy-User-Token)

响应:

json 复制代码
{
  "code": 0,
  "data": {
    "id": 1,
    "nickname": "微信用户",
    "avatar": "",
    "score": 0,
    "money": 0,
    "level": 1
  }
}

前端使用(UniApp)

javascript 复制代码
import { useUserStore } from '@/store/user'

const store = useUserStore()

// 小程序登录
const loginRes = await new Promise((resolve, reject) => {
  uni.login({ provider: 'weixin', success: resolve, fail: reject })
})
const data = await wxMappLogin(loginRes.code)
store.setToken(data.token)

// 公众号登录(H5)
const data = await oaAuthUrl(redirect)
window.location.href = data.url

// 获取用户信息
await store.fetchProfile()

// 登出
store.logout()

路由守卫

会员中心页面需要登录才能访问,在路由守卫中检查:

  • 访问 /user/* 路径时检查会员 Token
  • 未登录跳转到 /user/login
  • 支持白名单配置(无需登录的页面)