SpringBoot+阿里云短信服务实现发送短信验证码功能

目录

一、登陆阿里云,开通短信服务(收费的,需要充值,1元能发20条左右),并获取AccessKeyId和AccessKeySecret

二、创建短信模板与签名

三、引入依赖

四、准备工作已完成,编码环节开始,为了让代码简单直接,抛弃了开发规范~~

五、如何学习阿里短信API


        本篇文章为记录自己学习发送短信验证码小功能的过程,所有的调用三方接口的功能都如出一辙,在学习一个调用三方接口的过程中总结经验,再学习其他的,思路就会很清晰,就像我刚学完发送邮件(上一篇博客有总结),现在学发短信,很清楚自己该干什么。

一、登陆阿里云,开通短信服务(收费的,需要充值,1元能发20条左右),并获取AccessKeyId和AccessKeySecret

        AccessKeyId,用阿里云官网的话说,是访问阿里云API的密钥,一个用户可以有多个,每次向阿里云服务发送请求,需要带着AccessKeyId,阿里云接收到请求以后需要验证这个AccessKeyId-AccessKeySecret,验证通过才可进行访问,获取方法如下:

        1、开通短信服务

登陆以后,在搜索框直接搜索短信服务 控制台,进入控制台,未开通的会提示开通,直接开通即可

        2、进入AccessKey管理界面

        进入控制台后,鼠标放到右上角自己头像,会看到有个  管理AccessKeyId  选项

        3、点击创建,发送验证码验证即可创建成功

二、创建短信模板与签名

    1、创建短信模板,创建完模板后有个模板CODE,java代码需要用到

    2、创建签名

    验证码类型不需要上传什么证明 

三、引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<-- 阿里依赖 -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.3</version>
</dependency>
<-- 由于SpringBoot自带的jackson的API不如fastjson好用,所以又引入了依赖>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>

四、准备工作已完成,编码环节开始,为了让代码简单直接,抛弃了开发规范~~

    1、代码,注意,参数的属性名必须跟我的保持一致,例如设置短信签名request.putQueryParameter("SignName", signName),属性名必须为SignName,错一个字母就会报错

@RestController
@RequestMapping("/sms/test")
public class SmsTestController {
    // 阿里云获取的访问API密钥
    private static final String accessKeyId = "自己的accessKeyId";
    private static final String accessKeySecret = "自己的accessKeySecret";

    //短信签名,即最前面在【】这个中的文字,可以打开手机随便看一条商业短信,例:【淘宝】亲爱的用户.....
    private static final String signName = "自己的签名";

    // 短信模板,即在阿里云短信服务中自己创建的短信模板ID
    private static final String templateCode = "自己的模板ID";

    @RequestMapping(value = "/send", method = RequestMethod.POST)
    public ResultVO sendSms(String phone) throws ClientException {
        // 初始化acsClient,需要填写自己的accessKeyId和accessSecret
        // regionId只有一个杭州,不支持其他地区
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);

        // 组装请求对象,这几项为默认的设置,不必修改
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        // 阿里云服务器域名
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");

        // 短信接收者手机号
        request.putQueryParameter("PhoneNumbers", phone);
        // 短信签名
        request.putQueryParameter("SignName", signName);
        // 模板ID
        request.putQueryParameter("TemplateCode", templateCode);

        // 构建短信模板参数替换,要求格式为json
        // 如果你的短信模板为:验证码为:${code},那么你的json为:{"code": "2345"}
        Map<String, String> jsonParam = new HashMap<>();
        jsonParam.put("code", "2345");

        //此处我用的json格式化的依赖是fastjson,SpringBoot自带的是jackson
        request.putQueryParameter("TemplateParam", JSON.toJSONString(jsonParam));
        // 发送请求并获取响应,判断是否成功
        CommonResponse response = client.getCommonResponse(request);
        if (response.getHttpResponse().isSuccess()) {
            return ResultVO.success();
        }
        return ResultVO.fail();
    }
}

    2、代码解释

        1)accessKeyId和accessKeySecret是本篇文章第一节说的,不多说了

        2)signName短信签名,需要跟阿里云短信服务里自己创建并审核通过的签名保持一致,需要注意的是自己不需要加【】,阿里会自动给你的签名匹配上这个中文的中括号

        3)templateCode

五、如何学习阿里短信API

        在阿里短信服务控制台可以看到一个快速学习,点进去,然后选择查看 API Demo

 如下图:

这里有个比较详细的案例,有兴趣的小伙伴可以去看看,API文档每一个都介绍了是干嘛用的,是否必填,而且在中间那参数栏填了参数,最右侧的代码示例就会增加代码

实现用户手机号验证码登录可以分为以下几个步骤: 1. 用户输入手机号和验证码,点击登录按钮。 2. 后端接收到手机号和验证码后,先验证验证码是否正确。 3. 如果验证码正确,后端生成JWT token并将token存储到Redis中,同时将token返回给前端。 4. 前端将token存储到本地,以便后续请求时使用。 5. 后续请求时,前端需要在请求头中加入token,后端通过解析token来判断用户是否已登录。 下面是具体实现过程: 1. 在阿里云短信控制台创建短信模板,获取accessKeyId和accessKeySecret。 2. 在Spring Boot项目中添加依赖: ``` <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.0.3</version> </dependency> ``` 3. 实现发送短信验证码的接口: ``` @PostMapping("/sendSms") public Result sendSms(@RequestParam("phone") String phone) { // 生成随机验证码 String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000)); // 发送短信验证码 DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret); IAcsClient client = new DefaultAcsClient(profile); CommonRequest request = new CommonRequest(); request.setSysMethod(MethodType.POST); request.setSysDomain("dysmsapi.aliyuncs.com"); request.setSysVersion("2017-05-25"); request.setSysAction("SendSms"); request.putQueryParameter("RegionId", "cn-hangzhou"); request.putQueryParameter("PhoneNumbers", phone); request.putQueryParameter("SignName", "短信签名"); request.putQueryParameter("TemplateCode", "短信模板编号"); request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}"); try { CommonResponse response = client.getCommonResponse(request); // 将验证码存储到Redis中,有效期为5分钟 redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES); return Result.success("短信验证码发送成功"); } catch (Exception e) { return Result.error("短信验证码发送失败"); } } ``` 4. 实现用户手机号验证码登录的接口: ``` @PostMapping("/login") public Result login(@RequestParam("phone") String phone, @RequestParam("code") String code) { // 验证验证码是否正确 String redisCode = redisTemplate.opsForValue().get(phone); if (StringUtils.isBlank(redisCode)) { return Result.error("验证码已过期,请重新发送"); } if (!redisCode.equals(code)) { return Result.error("验证码不正确"); } // 生成JWT token,并存储到Redis中 String token = JwtUtils.generateToken(phone); redisTemplate.opsForValue().set(phone, token, 1, TimeUnit.DAYS); // 将token返回给前端 return Result.success(token); } ``` 5. 实现JWT token的生成和解析: ``` public class JwtUtils { private static final String SECRET_KEY = "jwt_secret_key"; // JWT密钥 private static final long EXPIRATION_TIME = 7 * 24 * 60 * 60 * 1000; // JWT过期时间(7天) public static String generateToken(String phone) { Date now = new Date(); Date expiration = new Date(now.getTime() + EXPIRATION_TIME); return Jwts.builder() .setSubject(phone) .setIssuedAt(now) .setExpiration(expiration) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static String getPhoneFromToken(String token) { try { Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody(); return claims.getSubject(); } catch (Exception e) { return null; } } } ``` 6. 在拦截器中验证token并获取用户信息: ``` public class JwtInterceptor implements HandlerInterceptor { private static final String AUTH_HEADER = "Authorization"; // token在请求头中的名称 @Autowired private StringRedisTemplate redisTemplate; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader(AUTH_HEADER); if (StringUtils.isBlank(token)) { throw new BusinessException("未登录或登录已过期"); } String phone = JwtUtils.getPhoneFromToken(token); if (StringUtils.isBlank(phone)) { throw new BusinessException("无效的token"); } String redisToken = redisTemplate.opsForValue().get(phone); if (StringUtils.isBlank(redisToken) || !redisToken.equals(token)) { throw new BusinessException("未登录或登录已过期"); } return true; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值