善逸:添加好友功能实现文档

添加好友功能实现文档

目标

实现一个添加好友的功能,具体流程如下:

  1. 被加好友根据自己的userId获取手机号和当前时间戳生成邀请码,并发送给另外一个人。
  2. 另外一个人根据要加好友的手机号和邀请码添加好友。

逻辑要求

  1. 自己不能关注自己,也不能关注不存在的人。
  2. 不能关注已经关注过的人。
  3. 邀请码五分钟内有效。

开发思路

1. 生成邀请码

首先,被加好友需要生成一个邀请码。邀请码的生成需要包含以下信息:

  • 被加好友的手机号
  • 当前时间戳

生成邀请码的步骤如下:

  1. 获取当前时间戳。
  2. 将手机号、一个固定的字符串(如"encode123")和时间戳拼接成一个字符串。
  3. 使用SHA-256算法对拼接后的字符串进行哈希处理。
  4. 将哈希结果编码为Base64字符串。
  5. 将Base64字符串和时间戳拼接成最终的邀请码。

2. 检查邀请码

当用户尝试添加好友时,需要对邀请码进行验证。验证步骤如下:

  1. 将邀请码拆分为哈希部分和时间戳部分。
  2. 检查时间戳是否在有效时间内(五分钟)。
  3. 重新生成哈希并与邀请码中的哈希部分进行比较。
  4. 检查用户是否尝试关注自己。
  5. 检查用户是否尝试关注不存在的用户。
  6. 检查用户是否已经关注过该好友。

3. 添加好友

在邀请码验证通过后,将用户与被加好友的关系存储到数据库中。

详细实现

生成邀请码的代码

long timestamp = System.currentTimeMillis();
String combinedString = param.get("phone").toString() + "encode123" + timestamp;

// 使用SHA-256生成哈希
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(combinedString.getBytes(StandardCharsets.UTF_8));

// 将哈希编码为Base64字符串
String inviteCode = Base64.getUrlEncoder().encodeToString(hash);

return inviteCode + "" + timestamp;
代码解析
  1. long timestamp = System.currentTimeMillis(); 获取当前时间戳。
  2. String combinedString = param.get("phone").toString() + "encode123" + timestamp; 将手机号、固定字符串和时间戳拼接成一个字符串。
  3. MessageDigest digest = MessageDigest.getInstance("SHA-256"); 获取SHA-256算法的实例。
  4. byte[] hash = digest.digest(combinedString.getBytes(StandardCharsets.UTF_8)); 对拼接后的字符串进行哈希处理。
  5. String inviteCode = Base64.getUrlEncoder().encodeToString(hash); 将哈希结果编码为Base64字符串。
  6. return inviteCode + "" + timestamp; 将Base64字符串和时间戳拼接成最终的邀请码。

检查邀请码的代码

@Override
public String checkFollowUser(Map param) throws NoSuchAlgorithmException {
    String inviteCode = param.get("invitedCode").toString();
    String[] parts = inviteCode.split("");
    if (parts.length != 2) {
        return "错误的邀请码";
    } else {
        String code = parts[0];
        long timestamp = Long.parseLong(parts[1]);

        // 检查是否在有效时间内
        long currentTime = System.currentTimeMillis();
        if (currentTime - timestamp > 5 * 60 * 1000) {
            return "邀请码已过期";
        } else {
            // 重新生成哈希并比较
            String expectedCode = generateInviteCode(param.get("phone").toString(), timestamp).split("")[0];
            if (expectedCode.equals(code)) {
                // 自己不能关注自己,也不能关注不存在的人
                // 也不能关注关注过的人
                long countMe = userDao.checkFollowUserMe(param);
                if (countMe > 0) {
                    return "不能关注自己";
                } else {
                    long countExist = userDao.checkFollowUser(param);
                    if (countExist == 0) {
                        return "关注的用户不存在";
                    } else {
                        long count = userDao.checkAlreadyFollowUser(param);
                        if (count > 0) {
                            return "已经关注该用户";
                        } else {
                            return null;
                        }
                    }
                }
            } else {
                return "无效的邀请码,想关注的用户与对应邀请码不匹配";
            }
        }
    }
}
代码解析
  1. String inviteCode = param.get("invitedCode").toString(); 获取邀请码。
  2. String[] parts = inviteCode.split(""); 将邀请码拆分为哈希部分和时间戳部分。
  3. if (parts.length != 2) { return "错误的邀请码"; } 检查邀请码格式是否正确。
  4. long timestamp = Long.parseLong(parts[1]); 获取时间戳。
  5. long currentTime = System.currentTimeMillis(); 获取当前时间。
  6. if (currentTime - timestamp > 5 * 60 * 1000) { return "邀请码已过期"; } 检查时间戳是否在有效时间内。
  7. String expectedCode = generateInviteCode(param.get("phone").toString(), timestamp).split("")[0]; 重新生成哈希。
  8. if (expectedCode.equals(code)) { ... } else { return "无效的邀请码,想关注的用户与对应邀请码不匹配"; } 比较哈希部分。
  9. long countMe = userDao.checkFollowUserMe(param); if (countMe > 0) { return "不能关注自己"; } 检查用户是否尝试关注自己。
  10. long countExist = userDao.checkFollowUser(param); if (countExist == 0) { return "关注的用户不存在"; } 检查用户是否尝试关注不存在的用户。
  11. long count = userDao.checkAlreadyFollowUser(param); if (count > 0) { return "已经关注该用户"; } 检查用户是否已经关注过该好友。

添加好友的代码

<!-- 关注用户 -->
<insert id="followUser" parameterType="Map">
    INSERT INTO user_follow (user_id, follow_user_id)
    SELECT
        #{userId} AS user_id,
        ui.user_id AS follow_user_id
    FROM
        user_info ui
    WHERE
        ui.phone = #{phone};
</insert>
代码解析
  1. <insert id="followUser" parameterType="Map"> 定义一个插入操作,参数类型为Map。
  2. INSERT INTO user_follow (user_id, follow_user_id) 插入数据到user_follow表。
  3. SELECT #{userId} AS user_id, ui.user_id AS follow_user_id FROM user_info ui WHERE ui.phone = #{phone}; 根据手机号查询被加好友的userId,并将用户与被加好友的关系存储到数据库中。

实现添加好友功能的好处

安全性

1. 使用SHA-256和Base64编码生成邀请码

  • 不可逆性:SHA-256是一种不可逆的哈希算法,确保了邀请码的安全性,即使被截获也无法轻易破解。
  • 唯一性:通过手机号和时间戳生成的哈希值保证了每个邀请码的唯一性,避免了重复和冲突。
  • 编码安全:Base64编码确保了哈希值在传输过程中不会因为特殊字符而导致问题。

2. 时间戳验证

  • 时效性:邀请码包含生成时的时间戳,并在验证时检查是否在五分钟内有效,防止邀请码被长期滥用。
  • 防止重放攻击:时间戳验证可以有效防止重放攻击,即使邀请码被截获,也只能在短时间内使用。

功能性

1. 防止自我关注

  • 逻辑检查:在验证邀请码时,检查用户是否尝试关注自己,避免了无意义的操作。

2. 防止关注不存在的用户

  • 用户存在性检查:在验证邀请码时,检查被加好友是否存在于系统中,确保关注操作的有效性。

3. 防止重复关注

  • 重复关注检查:在验证邀请码时,检查用户是否已经关注过该好友,避免重复关注。

用户体验

1. 简单易用

  • 邀请码生成和验证:用户只需生成邀请码并发送给好友,好友在添加时输入邀请码即可完成关注操作,流程简单明了。

2. 快速响应

  • 即时验证:通过时间戳和哈希值的验证,可以快速判断邀请码的有效性,提升用户体验。

可维护性

1. 清晰的代码结构

  • 模块化设计:生成邀请码、验证邀请码和添加好友的逻辑分开实现,代码结构清晰,易于维护和扩展。
  • 注释和文档:详细的注释和文档说明了每个步骤的实现逻辑,便于后续开发人员理解和维护。

2. 数据库操作的封装

  • SQL语句封装:将数据库操作封装在XML文件中,便于修改和管理。

扩展性

1. 灵活的参数配置

  • 参数化设计:通过Map传递参数,便于后续扩展和修改,如增加新的验证逻辑或参数。

2. 可扩展的验证逻辑

  • 逻辑检查:当前实现了防止自我关注、关注不存在的用户和重复关注的逻辑,后续可以根据需求增加更多的验证逻辑,如黑名单检查等。

膳逸

Base URLs:

Authentication

shanyi-api

POST 关注用户

POST /user/followUser

前端提交userId与要关注的用户的uuid以及邀请码,后端实现关注用户。
要注意1、自己不能关注自己,也不能关注不存在的人
2、还不能关注关注过的人
3、邀请码设计
3、邀请码设计

Body 请求参数

{
  "userId": 5,
  "phone": "15553581028",
  "invitedCode": "1lNxOsO0-oFJRAMcUL9Q3dM7HaF2WjGl-nMO3tJgY2c=1719044274146"
}

请求参数

名称位置类型必选说明
tokenheaderstringnone
bodybodyobjectnone
» userIdbodyinteger我的id
» phonebodystring要关注的那个人的uuid
» invitedCodebodystring邀请码

返回示例

成功

{
    "userId": 5,
    "phone": "15935883218",
    "invitedCode": "c2WCNNcuXqTryIGz_QD8P5kFlsDV1Wzw5bqYeodkKr4=1718474341408"
}
{
  "msg": "success",
  "code": 200
}

不能关注自己

{
    "userId": 5,
    "phone": "13621403803",
    "invitedCode": "4FwIJAffAcKNIgsh8eQv7VKlVasKzagtD4wkTZxQoMs=1719044129755"
}
{
  "msg": "不能关注自己",
  "code": 500
}

已经关注该用户

{
    "userId": 5,
    "phone": "15553581028",
    "invitedCode": "1lNxOsO0-oFJRAMcUL9Q3dM7HaF2WjGl-nMO3tJgY2c=1719044274146"
}
{
  "msg": "已经关注该用户",
  "code": 500
}

错误的邀请码

{
    "userId": 5,
    "phone": "15553581028",
    "invitedCode": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
{
  "msg": "错误的邀请码",
  "code": 500
}

邀请码已过期

{
    "userId": 5,
    "phone": "15553581028",
    "invitedCode": "1lNxOsO0-oFJRAMcUL9Q3dM7HaF2WjGl-nMO3tJgY2c=1719044274146"
}
{
  "msg": "邀请码已过期",
  "code": 500
}

返回结果

状态码状态码含义说明数据模型
200OK成功Inline

返回数据结构

状态码 200

名称类型必选约束中文名说明
» codeintegertruenonenone
» msgstringtruenonenone

POST 生成邀请码

POST /user/generatingInvitedCode

根据userId(查找uuid)和当前时间生成5分钟有效的邀请码

Body 请求参数

{
  "userId": "4"
}

请求参数

名称位置类型必选说明
tokenheaderstringnone
bodybodyobjectnone
» userIdbodystringnone

返回示例

成功

{
  "msg": "success",
  "result": "DjAUnHoBHUaFmenKFJrGmNv-OHFSKzvqOXCW4xHMb1I=----1716435888948",
  "code": 200
}

返回结果

状态码状态码含义说明数据模型
200OK成功Inline

返回数据结构

状态码 200

名称类型必选约束中文名说明
» codeintegertruenonenone
» msgstringtruenonenone
» resultstringtruenonenone

结论

通过上述代码实现了添加好友的功能,确保了用户不能关注自己、不能关注不存在的人以及不能重复关注同一个人。同时,邀请码在五分钟内有效,保证了安全性和时效性。

关键点总结

  • 邀请码生成:使用SHA-256算法和Base64编码生成唯一的邀请码。
  • 邀请码验证:确保邀请码在有效时间内,并且与被加好友的手机号匹配。
  • 逻辑检查:防止用户关注自己、关注不存在的用户以及重复关注同一个用户。
  • 数据库操作:将用户与被加好友的关系存储到数据库中。

通过以上步骤,完整地实现了添加好友的功能,满足了所有的逻辑要求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值