基于华为云短信与Redis的登录鉴权系统实践 | 华为云消息&短信 MSGSMS实战【玩转华为云】

举报
柠檬味拥抱 发表于 2025/09/07 14:54:25 2025/09/07
【摘要】 本文将介绍如何利用 华为云短信服务 实现验证码登录,结合 Redis校验 提升性能与安全性,并通过 双重拦截模式 来实现权限控制和 Token 自动刷新,最终构建一个安全、流畅的用户登录体验。

基于华为云短信与Redis的登录鉴权系统实践 | 华为云消息&短信 MSGSMS实战【玩转华为云】

引言

在现代互联网应用中,用户登录与鉴权是确保系统安全性与用户体验的关键环节。传统的用户名+密码登录方式不仅繁琐,还存在被盗号、弱密码等风险。为了提升安全性与便捷性,许多系统采用了 短信验证码登录 结合 Token鉴权机制 的方式。
image.png

本文将介绍如何利用 华为云短信服务 实现验证码登录,结合 Redis校验 提升性能与安全性,并通过 双重拦截模式 来实现权限控制和 Token 自动刷新,最终构建一个安全、流畅的用户登录体验。


在这里插入图片描述

华为云消息&短信 MSGSMS

华为云提供的 消息&短信(MSGSMS)服务,能够高效、稳定地完成短信验证码发送。配合 Redis 缓存验证码 与 Token 鉴权机制,我们可以构建一个既安全又高效的用户登录系统。

image.png

华为云消息&短信服务(MSGSMS)是华为云提供的一套 云端消息推送和短信发送服务,主要用于向用户发送:

  • 短信验证码(如登录验证码、支付验证码)

  • 营销通知短信(如活动通知、优惠券推送)

  • 事务性通知(如订单状态变更、物流信息)

MSGSMS 是一个 高可用、可扩展的云端服务,支持海量并发短信发送,同时提供可靠的状态回执和统计功能,方便企业进行管理和分析。

image.png

使用流程

华为云消息&短信(MSGSMS)国内短信使用流程可概括为:首先,企业用户需注册华为云账号并完成实名认证,开通消息&短信服务;随后在短信控制台创建短信应用,获取 APP_Key、APP_Secret 及接入地址,并完成短信资质报备;接着申请短信签名和短信模板,分别遵循审核规范,签名一般需 7-10 个工作日,模板约 2 小时;可根据业务需求订购短信套餐包;最后,通过 API 或群发助手发送短信,并可通过状态回执接口查看发送状态及处理失败情况,实现完整的短信发送管理闭环。

image.png

技术架构

整体方案的核心流程如下:

  1. 用户请求验证码
    前端输入手机号,后端调用华为云短信服务接口,发送随机验证码,并存入 Redis,设置有效期(如 5 分钟)。

  2. 用户提交验证码登录
    后端从 Redis 校验验证码是否正确、是否过期;若校验通过,则生成随机 Token,并返回给前端。

  3. Token 鉴权
    前端请求需要鉴权的接口时,携带 Token,后端通过拦截器进行校验,确保用户身份合法。

  4. 双重拦截模式

    • 权限拦截:校验用户是否已登录、是否有权限访问对应资源。
    • 状态刷新拦截:若 Token 即将过期但仍处于活跃使用状态,自动刷新 Token 过期时间,提升用户的连续使用体验。

在这里插入图片描述

核心代码实现

1. 华为云短信验证码发送

public String sendSmsCode(String phone) {
    String code = String.valueOf(new Random().nextInt(899999) + 100000);
    // 调用华为云短信接口
    smsClient.send(phone, code);

    // 将验证码存入Redis,有效期5分钟
    redisTemplate.opsForValue().set("login:code:" + phone, code, 5, TimeUnit.MINUTES);

    return "验证码已发送";
}

2. 验证码校验与Token生成

public String login(String phone, String code) {
    String redisCode = redisTemplate.opsForValue().get("login:code:" + phone);

    if (redisCode == null || !redisCode.equals(code)) {
        throw new RuntimeException("验证码错误或已过期");
    }

    // 验证成功,生成随机Token
    String token = UUID.randomUUID().toString();
    redisTemplate.opsForValue().set("login:token:" + token, phone, 30, TimeUnit.MINUTES);

    return token;
}

3. Token 拦截器(权限校验)

public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader("Authorization");
        if (token == null || redisTemplate.opsForValue().get("login:token:" + token) == null) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        return true;
    }
}

4. 双重拦截模式(权限+状态刷新)

public class RefreshInterceptor implements HandlerInterceptor {
    private static final long REFRESH_THRESHOLD = 5 * 60; // 5分钟

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader("Authorization");
        Long expire = redisTemplate.getExpire("login:token:" + token, TimeUnit.SECONDS);

        if (expire != null && expire < REFRESH_THRESHOLD) {
            // 刷新Token过期时间
            redisTemplate.expire("login:token:" + token, 30, TimeUnit.MINUTES);
        }
        return true;
    }
}

技术难点与优化

  1. 验证码防刷机制

    • 通过 限流(如每个手机号 60 秒内只能获取一次验证码)避免短信轰炸。
    • Redis 中记录验证码请求时间,超出频率则拒绝发送。
  2. Token 安全性

    • Token 使用 UUID 或 JWT(Json Web Token) 生成,保证唯一性和可扩展性。
    • 可在 JWT 中存储用户ID、角色信息,实现更细粒度的权限控制。
  3. 双重拦截的意义

    • 权限拦截 保证了系统安全,未登录用户无法访问敏感接口。
    • 状态刷新拦截 提升了用户体验,避免频繁要求重新登录,尤其适合需要长时间在线的业务场景(如 IM、后台管理系统)。

在这里插入图片描述

总结

本文介绍了一个完整的 短信验证码 + Redis 校验 + Token 鉴权 登录方案,并重点讲解了 双重拦截模式 的应用。

该方案兼顾了 安全性用户体验,适用于大部分中大型互联网应用的登录与鉴权场景。通过合理的验证码防刷、Token 刷新策略,可以让用户在安全环境中获得更流畅的使用体验。

未来可以结合 OAuth2.0多因子认证(MFA),进一步增强系统的安全性和扩展性。

附录:面试题问题与回答

1. 你在项目中为什么要使用短信验证码登录,而不是传统的用户名+密码?

回答:
传统用户名+密码存在弱密码、遗忘、被撞库等风险,用户体验也不佳。短信验证码更便捷,用户只需手机号即可登录,降低了使用门槛,同时结合 Redis 设置验证码有效期,可以有效防止重复使用,提升了安全性和便捷性。


2. 验证码为什么要存放在 Redis,而不是数据库?

回答:
验证码有 高频访问 + 短生命周期 的特点,适合放在内存型数据库中。

  • Redis 读写性能高,支持过期时间设置,非常适合验证码场景。
  • 如果用数据库,会产生大量无效数据,清理成本高,并且查询性能不如 Redis。

3. 你们的 Token 是怎么生成和存储的?

回答:

  • Token 采用 UUID 随机生成JWT(Json Web Token)
  • 登录成功后,Token 会存入 Redis,设置过期时间,比如 30 分钟。
  • 每个请求都带上 Token,服务端通过 Redis 校验其有效性,保证了轻量级的分布式认证。

4. 为什么要用双重拦截模式?能详细讲讲吗?

回答:
双重拦截主要包括:

  1. 权限拦截:拦截未登录或无权限的请求,保证接口安全。
  2. 状态刷新拦截:检测 Token 是否即将过期,如果还在活跃使用,就自动延长过期时间,避免用户频繁登录。

这样既保证了安全性,又提升了用户的连续使用体验。


5. Token 如何防止被窃取后滥用?

回答:

  • Token 绑定用户信息(如手机号/用户ID),即使被盗也只能冒充该用户。
  • 设置较短的过期时间,降低风险。
  • 结合 IP + User-Agent 校验,发现异常使用时强制下线。
  • 可以配合 HTTPS 加密传输,防止 Token 被中间人攻击窃取。

6. 如果用户频繁请求验证码,怎么防止短信轰炸?

回答:

  • 使用 Redis 限流策略,比如 60 秒内同一手机号只能请求一次验证码。
  • 统计单个 IP 或手机号在一定时间段内的请求次数,超过阈值直接拒绝。
  • 可以结合滑块验证码、人机验证进一步提高安全性。

7. 为什么要设计 Token 刷新机制?直接重新登录不行吗?

回答:
直接重新登录会打断用户体验,尤其在长时间使用的系统(如管理后台、IM 聊天)里影响较大。
通过刷新机制:

  • 在 Token 即将过期时自动延长有效期;
  • 只要用户在持续使用系统,就不需要重新登录;
  • 如果用户长时间不活跃,Token 会自然过期并失效,保证安全性。

8. 如果系统是分布式部署的,Token 鉴权怎么保证一致性?

回答:

  • Token 信息存放在 Redis,而不是单机内存。
  • Redis 本身支持分布式部署和持久化,能保证多个服务实例共享 Token 状态。
  • 这样不管请求落在哪个服务实例上,都能保证鉴权一致性。

9. 你为什么选择 Redis 存储 Token,而不是 JWT 自包含?

回答:
JWT 自包含(不依赖服务端存储)有优点,但也存在问题:

  • 无法提前让 Token 失效(比如用户主动退出或强制下线)。
  • 一旦签发,就必须等到过期才失效。

我选择 Redis 存储 Token,原因是:

  • 能动态控制 Token 生命周期。
  • 支持手动注销、强制下线。
  • 能结合双重拦截实现 Token 自动续期

10. 如果 Redis 宕机了,登录系统会怎么处理?

回答:

  • 可以启用 Redis Cluster/哨兵模式,保证高可用性。
  • 对验证码和 Token 这种业务,Redis 持久化不是必须的,短暂宕机会影响用户体验,但不会导致严重数据丢失。
  • 一般会设置降级策略,比如临时拒绝验证码请求,提示用户稍后重试。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。