浅谈棋牌游戏开发流程三:核心业务逻辑(一)——用户系统与登录流程

一、前言:从“陌生人”到“正式玩家”的关键一环

在一款棋牌游戏里,每个玩家进入游戏时,都要先建立一层“身份”——这就是所谓的用户系统。没有用户系统,玩家就只能是一个“路过群众”,既没有专属账号,也无法记录金币、积分或胜率,更谈不上充值或商城。

所以,用户系统就像一扇门,玩家通过这扇门才能走进游戏的“世界”里。对于后端来说,如何设计这扇门,直接影响到后续的数据管理、安全、支付以及各种运营策略。

本篇我们就聚焦在**“用户系统与登录流程”**上,从以下几个方面展开:

  1. 账号体系的多种形态(游客、注册账号、第三方登录等);
  2. 基础数据库表设计和数据存储;
  3. 登录流程与 Token/Session 机制;
  4. 常见的安全措施与防护点;
  5. 实际开发中的一些细节与常见坑;
  6. 后续如何结合支付、实名制、风控等更高级需求。

希望通过本文,让你对“用户系统”从无到有的构建过程有一个完整的认识。


二、账号体系:多种“身份”选择,满足不同玩家需求

说到账号体系,很多人可能会先想到**“手机号+密码”“邮箱+密码”**的传统注册方式。但对于棋牌游戏来说,考虑到推广速度、用户习惯、平台限制等,往往会提供多样化的登录方式。

2.1 游客登录

  • 特点

    1. 无需繁琐注册,一键进入游戏;
    2. 最适合“先体验后绑定”的模式,能快速留住初次下载的用户;
    3. 只需在本地生成一个唯一设备 ID(或 UUID),在后端做记录即可。
  • 优点

    • 降低新玩家的注册门槛,提升初次留存;
    • 省去了输入手机号/验证码的麻烦,让用户先尝尝“甜头”。
  • 缺点

    • 游客账号往往只能绑定在当前设备,一旦卸载或更换手机,用户数据就可能丢失;
    • 不利于深度运营,比如无法做精准营销,因为游客信息是匿名且缺乏完整资料。

常见做法

  • 后端分配给游客一个 guest_id,同时下发一个 Token;
  • 提醒玩家后续可**“绑定手机号/微信”**等,以防数据遗失。

2.2 注册账号(手机号、邮箱、用户名)

  • 传统而通用

    • 玩家可以通过输入手机号+验证码,或者邮箱+密码,来注册一个正式账号;
    • 后端存储账号信息、密码(加密后)以及玩家基本资料(昵称、头像、性别、地区等)。
  • 适用场景

    • 想构建更完整的用户社区或积分体系;
    • 对实名制或防沉迷有较高要求(需要手机号绑定)。
  • 要点

    1. 密码加密:不在数据库中存明文,至少用 bcrypt/SHA256 + Salt。
    2. 验证码流程:手机号注册时常用短信验证码,需要接第三方短信服务;邮箱可以发激活邮件。
    3. 防止恶意批量注册:可以对同一 IP 或同一设备做频率限制。

2.3 第三方登录(微信/QQ/苹果/Google等)

  • 优势

    1. 大幅提升注册转化率:玩家只要点“微信一键登录”就搞定,无需再输入任何信息;
    2. 可以获取一定的社交关系或头像、昵称,让游戏里好友系统更容易落地(例如使用微信好友列表)。
  • 流程

    1. 客户端拉起第三方授权页,玩家同意授权后,会拿到一个授权码access_token
    2. 后端携带此授权码去第三方服务器验证,拿到用户唯一标识(如 openidunionid),并获取用户基本资料(头像、昵称等);
    3. 后端将此第三方标识和本游戏的用户账号进行绑定,如果是新用户就自动创建一个账号并分配 Token。
  • 注意点

    1. 刷新令牌:有些第三方登录的 access_token 有效期有限,要处理续期;
    2. 与游客账号合并:如果玩家先以游客身份玩了一阵子,再用微信登录,如何把两者的数据合并?需要做逻辑处理。
    3. 不同平台之间的互通:如果玩家在 iOS 上用苹果登录,在安卓上又用微信登录,是否可视为同一个账号?这需要提前定义策略。

2.4 账号合并与绑定

  • 为什么要做
    • 可能同一个玩家,一开始用游客账号试玩,然后又想绑定微信,再后来还想绑定手机号,以保证多端登录数据同步;
    • 防止一个玩家拥有多个账号在同一个区服内作弊,或者多开引发问题。
  • 如何做
    • 在数据库层面,对“用户账号表”做一个唯一用户 ID(如 user_id),每种登录方式(游客/微信/手机号)都是这 user_id 下的子记录;
    • 如果游客帐号和微信帐号绑定,就把这两种登录方式统一映射到同一个 user_id 上。

三、数据库表设计:用户相关的数据如何落地

无论你是用 MySQL 还是其他数据库,都需要规划一个(或多个)表来存储用户信息。以下是一个常见的简化设计示例,供参考:

-- 用户主表:user_info
CREATE TABLE user_info (
    user_id       BIGINT PRIMARY KEY AUTO_INCREMENT, 
    nickname      VARCHAR(50) NOT NULL,
    avatar_url    VARCHAR(255),
    gender        TINYINT,         -- 0未知/1男/2女
    create_time   DATETIME NOT NULL,
    update_time   DATETIME NOT NULL
);

-- 账号表:user_account,用于存储各种登录方式
CREATE TABLE user_account (
    account_id    BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id       BIGINT NOT NULL,     -- 与 user_info.user_id 关联
    account_type  TINYINT NOT NULL,     -- 1手机号 2微信 3游客 4苹果 5QQ ...
    account_key   VARCHAR(100) NOT NULL, -- 对应手机号、openId或游客ID等
    password_hash VARCHAR(100),        -- 如手机号、邮箱需要存密码
    create_time   DATETIME NOT NULL,
    update_time   DATETIME NOT NULL
);

-- 用户资产表:user_assets(可选)
CREATE TABLE user_assets (
    user_id       BIGINT NOT NULL,
    gold_coins    BIGINT NOT NULL DEFAULT 0,  -- 金币数
    diamonds      BIGINT NOT NULL DEFAULT 0,  -- 钻石数等虚拟货币
    ...
    update_time   DATETIME NOT NULL
);

-- 其他:手机验证表、登录日志表等按需求设计

关键思路

  1. user_info 维护一个独立的 user_id,记录玩家的基本资料;
  2. user_account 管理具体的登录方式,可以同时存在多条记录(一个 user_id 对应多个登录方式);
  3. 密码要用hash形式存储(bcrypt 或其他安全哈希),不要存明文;
  4. 游客账号可以用 account_type=3account_key 存储一个 UUID;微信账号可以用 account_type=2account_key 存 openId 等。

这样设计能方便后续对账号合并、绑定等操作,也易于扩展更多第三方登录方式。


四、登录流程与 Token / Session 机制

4.1 为什么需要 Token 或 Session?

  • 保持玩家的登录状态:当玩家成功登录后,后端要给他一个“凭证”,以便在之后的请求里验证其身份;
  • 减少重复鉴权开销:不必每次请求都重复输入账号密码或重新与第三方校验;
  • 安全保护:Token 或 Session 可以设置过期时间、刷新机制,防止长期有效的凭据被盗用。

4.2 常见实现方式

  1. 后端 Session + Cookie

    • 传统 Web 里常用的方式:玩家登录后,后端在服务器内存/Redis 里存一条会话(Session),同时给浏览器下发一个 Session ID 放在 Cookie 中;
    • 适用于传统网页端。如果做移动端/Unity/Cocos 原生 App,就不太方便依赖浏览器的 Cookie 机制。
  2. JWT(JSON Web Token)

    • 一种常见的“无状态” Token,玩家每次请求都在 HTTP Header 或 WebSocket 消息中带上该 Token;
    • 服务器验证 Token 的签名和内容,如果通过就认定你是某个 user_id;
    • 通常还会搭配 Redis 或数据库来判断 Token 是否过期、是否已被撤销。
  3. 自定义 Token

    • 可以自己定义一段随机字符串或带签名的字符串,成功登录后存到 Redis,客户端每次请求都带上该字符串;
    • 后端验证此字符串是否在 Redis 中且未过期,就认定用户登录有效。
    • 过期后需要重新登录或刷新 Token。

棋牌项目常见实践

  • 移动端/原生客户端:更多会用 自定义 Token + Redis 方案,或者 JWT
  • H5/小程序:可用 sessionKey 等机制,或也用自定义 Token。
  • Token 刷新机制:给 Token 设置一个相对短的过期时间,比如 7 天,客户端到期前自动请求刷新,减少长期 Token 泄露的风险。

4.3 示例:自定义 Token 流程

以下是一个简化的“手机号+验证码”登录流程示例,返回自定义 Token:

  1. 玩家请求发送验证码

    • POST /api/sendCode,带上手机号;
    • 后端生成随机验证码,存到 Redis 并发短信(或者走 Mock 短信,视环境而定)。
  2. 玩家提交验证码登录

    • POST /api/loginByPhone,包含 { phone: xxx, code: yyy }
    • 后端验证 Redis 中存的验证码是否正确、是否过期;如果通过,则继续。
    • 如果这是新用户,就在数据库里创建 user_info & user_account
    • 最后生成一个随机 token(比如使用 UUID + 加密签名),存到 Redis(key=token, value=user_id, 以及过期时间),然后返回给客户端:
      {
        "code": 0,
        "msg": "ok",
        "data": {
          "token": "xxxxxx",
          "user_id": 12345,
          "nickname": "小明"
        }
      }
      

  3. 后续请求

    • 客户端在请求头里带 Authorization: Bearer xxxxxx 或者随意定义一个 header;
    • 后端解析出 token 去 Redis 查一下是否存在且未过期,如果有效,就拿到 user_id,代表这是哪个玩家,否则拒绝访问或返回未登录。

优点

  • 这样玩家不需要保留服务器的 Session 状态,所有信息都以 token+user_id 的方式来验证;
  • 方便在分布式部署里横向扩容,因为 Redis 做了共享存储,任何服务器节点都能校验 token。

五、安全措施:用户系统里的“防火墙”

棋牌游戏尤其要注意安全,因为这里有与金钱、道具直接挂钩的充值、提现等功能,更要重视账号和资产的安全。

5.1 数据加密与密码保护

  • 密码存储:如前文所说,一定要哈希并加盐 (bcrypt、scrypt 或 Argon2 等),不能明文存储;
  • 通信加密:最好使用 HTTPS / WSS,尤其登录、充值等关键接口必须加密;
  • Token 签名:若使用 JWT 或自定义 Token,要有服务端私钥签名,防止被伪造。

5.2 防止暴力破解或撞库

  • 验证码/图形验证码:玩家密码或验证码输入错误过多,要有验证码拦截;
  • IP/设备风控:同一个 IP 或同一个设备频繁注册或登录失败,可能是攻击行为,可临时封禁;
  • 加固后端接口:不要仅依赖客户端判断,所有校验都要在服务端进行。

5.3 防止账号盗用与异常检测

  • 异常登录提醒:如一个账号在极短时间内在两个地理位置登录,可触发风控提醒;
  • 二次验证:对涉及财产操作(提现、赠送道具)时,可要求二次验证码或密码确认;
  • 日志审计:记录所有登录IP、时间、设备信息,出现纠纷或投诉时可追溯。

六、融合游客模式、第三方登录与正式账号:一个示例流程

为了说明多登录模式如何融合,这里给出一个更完整的示例:

  1. 初次进入

    • 玩家下载 App,点击“快速开始”-> 后端创建游客账号 account_type=3 + account_key=uuid
    • 返回一个 token,客户端拿到后就能进入游戏大厅。
    • 数据库里 user_info 新增一条 user_id=1001nickname="游客xxxxx";在 user_account 表里插入游客记录。
  2. 玩家体验一段时间,想绑定微信

    • 客户端点“微信登录”-> 微信授权成功,返回 openid=AABBCC
    • 后端先查 user_account 表有没有 account_key=AABBCC,如果没有,说明这是第一次微信登录;
    • 将此微信账号记录绑定到同一个 user_id=1001 上,更新昵称、头像等;
    • 以后玩家既可以用游客方式进,也能用微信直接登录(都指向 user_id=1001 同一份数据)。
  3. 玩家换设备或卸载重装

    • 如果用游客登录,之前的游客账号数据就找不到了(除非能凭设备ID匹配上),所以更好的方式是让他用微信登录,从而找回之前的 user_id=1001
    • 这时就不会丢失金币或战绩,体验也更好。
  4. 后续绑定手机号

    • 同理,如果玩家想再绑定手机号,可以再加一条 account_type=1, account_key=手机号

这个过程让玩家既能“轻量化”体验,也能后续“正规化”操作,一举两得。


七、与支付、实名制、风控的结合

用户系统还与游戏的支付充值、实名制、防沉迷等密切相关。虽然本篇主要聚焦登录部分,但稍微提一下:

  1. 支付充值

    • 只有在“用户信息”里有明确的 user_id 后,才能对应到后端的订单系统;
    • 充值成功后,会在 user_assets 里更新金币/钻石数量;
    • 如果用户账号异常,可冻结其充值或提现功能。
  2. 实名制

    • 一些国家/地区要求游戏必须做实名验证,特别是针对未成年人防沉迷;
    • 可以在用户系统里加一列 id_card_no(身份证号或其他证件号),或在绑定手机号时做实名认证。
    • 游客账号通常无法进行充值或深度玩法,必须在绑定实名后才开放。
  3. 风控与防沉迷

    • 监控玩家的在线时长、充值额度、登录频率,一旦超过某个阈值,就触发相应限制;
    • 对异常账号(比如频繁提现、注册)进行风控,必要时封号处理。

八、常见问题与实践建议

8.1 如何防止重复注册、占用用户名?

  • 用户名/昵称
    • 可以允许重复,但加个数字后缀(类似“张三#1234”);
    • 也可以只允许唯一,但需要在注册或修改昵称时做唯一校验。
  • 手机号
    • 一个手机号只能绑定一个 user_id
    • 如果要解绑,需要明确流程,不能让同一个手机号反复绑定不同账号。

8.2 一个账号多处登录冲突怎么处理?

  • 顶号
    • 当检测到同一个账号在另一台设备上登录,可以挤掉前一个会话;
    • 这时可以在前端弹提示“你的账号在其他设备登录,当前已下线”。
  • 允许多端同时在线
    • 也可以允许多设备登录,但要注意房间同步问题和异常监控(有人用多设备操控同一账号做不正当操作)。

8.3 Token 过期后玩家体验

  • 自动刷新
    • 在 Token 过期前几小时或几天,客户端可主动向服务器请求刷新;
    • 如果 Token 已过期,则跳转到登录界面或自动用第三方授权重新登录。
  • 严格模式
    • 过期就是过期,必须重新登录输入密码或拉起授权,提升安全性。

8.4 游客账号丢失数据如何避免?

  • 在设备上存储游客标识
    • 如果玩家重装后设备ID没变,可以尝试匹配到以前的游客账号;
    • 但不保证所有系统都能保持同样的设备ID。
  • 及时引导绑定
    • 给游客适度的福利或提示,鼓励他们尽快绑定微信/手机号,避免账号丢失。

九、示例代码:一个简易的“登录”后端伪实现

以下是一个Node.js + Express 的简易伪代码示例,展示手机号+验证码以及第三方登录的一些核心逻辑。真实项目中肯定比这复杂,但可以帮助理解流程。



// pseudo-user-controller.js
const express = require('express');
const router = express.Router();
const crypto = require('crypto');
const { getUserByPhone, createUser, updateUserNickname } = require('./userService');
const { redisClient } = require('./redisClient');

function generateToken() {
  // 简易随机token,不建议用于生产环境
  return crypto.randomBytes(16).toString('hex');
}

// 发送验证码接口
router.post('/sendCode', async (req, res) => {
  const { phone } = req.body;
  if (!phone) {
    return res.json({ code: 1, msg: '手机号不能为空' });
  }
  // 生成随机验证码, 例如 6位数字
  const code = Math.floor(100000 + Math.random() * 900000).toString();
  // 写入Redis, 有效期5分钟
  await redisClient.set(`PHONE_CODE_${phone}`, code, 'EX', 300);

  // TODO: 调用短信服务发送验证码
  console.log(`模拟发送短信: phone=${phone}, code=${code}`);

  res.json({ code: 0, msg: '验证码已发送' });
});

// 手机号+验证码登录
router.post('/loginByPhone', async (req, res) => {
  const { phone, code } = req.body;
  if (!phone || !code) {
    return res.json({ code: 1, msg: '缺少参数' });
  }

  const redisKey = `PHONE_CODE_${phone}`;
  const realCode = await redisClient.get(redisKey);
  if (!realCode) {
    return res.json({ code: 2, msg: '验证码已过期' });
  }
  if (realCode !== code) {
    return res.json({ code: 3, msg: '验证码错误' });
  }

  // 验证通过后,删除redis中的验证码
  await redisClient.del(redisKey);

  // 查询是否已有用户
  let user = await getUserByPhone(phone);
  if (!user) {
    // 创建新用户
    user = await createUser({ phone });
  }

  // 生成token并写入Redis
  const token = generateToken();
  await redisClient.set(`TOKEN_${token}`, user.user_id, 'EX', 7 * 24 * 3600); // token7天过期

  res.json({
    code: 0,
    msg: '登录成功',
    data: {
      token,
      user_id: user.user_id,
      nickname: user.nickname
    }
  });
});

// 示例:微信登录
router.post('/loginByWeChat', async (req, res) => {
  const { wechatCode } = req.body;
  // 1. 客户端先拿到wechatCode(小程序或App拉起微信授权)
  // 2. 后端用wechatCode去微信服务器换取openid/unionid等信息
  const openid = `mockOpenId_${wechatCode}`;
  // 3. 查找账号表中是否有对应openid
  let user = await getUserByOpenId(openid);
  if (!user) {
    // 新建一个账号, 并生成 user_info
    user = await createUser({ wechatOpenId: openid });
  }

  // 4. 生成token
  const token = generateToken();
  await redisClient.set(`TOKEN_${token}`, user.user_id, 'EX', 7 * 24 * 3600);

  res.json({
    code: 0,
    msg: '微信登录成功',
    data: {
      token,
      user_id: user.user_id,
      nickname: user.nickname
    }
  });
});

module.exports = router;

说明

  • 核心思路:将登录凭证(token -> user_id)保存在 Redis,约定有效期;客户端必须在后续请求头里带此 Token 才能访问受保护的接口。
  • 第三方登录流程中,weChatCode 的部分略去了真实的微信 API 请求,只留了示例逻辑,现实中需要调用微信的 auth.code2Session 等接口。

十、总结:用户系统是“留存与变现”的基石

从本篇里,我们可以看到:

  1. 账号体系多样化:游客、手机号、第三方社交账号……每一种都对应不同的场景和需求;
  2. 数据库设计user_info 记录通用信息,user_account 管理具体账号绑定,资产表、日志表可进一步扩展;
  3. 登录流程:无论是自定义 Token、JWT 还是 Session,都要保证安全性和过期管理;
  4. 安全防护:密码加密、验证码、风控策略都必不可少;
  5. 绑定与合并:一开始玩家可能是游客身份,后面再绑定微信或手机号形成正式账号,这种流程要在后端实现良好的兼容和合并逻辑;
  6. 和支付、实名制、风控的紧密联系:用户系统不仅仅是登录而已,还关系到游戏的营收和监管。

在棋牌游戏开发中,用户系统绝对算是“牵一发而动全身”的模块——任何环节都离不开账号数据的支持。打好这个地基,才能让后面的玩法、充值、活动等功能顺利展开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值