Spring Boot 注册登录 demo 使用 Spring Security 和发送短信验证码

本贴最后更新于 1005 天前,其中的信息可能已经沧海桑田

@[TOC]

1、前言

接上文 SpringBoot 整合 Spring Security 实现自定义页面以及验证码登录

环境版本说明

MongoDB:5.0.6
SpringBoot:2.5.3
JDK:1.8

2、腾讯云短信 api

介绍

本 demo 使用免费赠送的腾讯云短信
https://curl.qcloud.com/a18eCzrO 短信试用有 100 个
https://console.cloud.tencent.com/smsv2 在这里通过模板还会赠送 100 个
如果不够可以购买

如果觉得短信验证麻烦可换成邮箱验证码

3、主要代码

完整代码链接放文末

pom.xml

这里建议根据 api 文档更换 jar 版本
https://console.cloud.tencent.com/api/explorer?Product=sms

		<!--邮件依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
      <!-- https://mvnrepository.com/artifact/com.tencentcloudapi/tencentcloud-sdk-java-sms -->
        <dependency>
            <groupId>com.tencentcloudapi</groupId>
            <artifactId>tencentcloud-sdk-java-sms</artifactId>
            <version>3.1.468</version>
        </dependency>

application.yml

sendSms:
  SecretId:  你的账号API 密钥id
  SecretKey: 你的账号API 密钥
  SmsSdkAppId: 你的短信应用id
  TemplateId: 你的短信模板id

获取 SecretId 和 SecretKey

这里的账号 api 密钥 https://console.cloud.tencent.com/cam
快速创建账户,或者直接使用主账号
如图 访问方式使用: 编程访问;用户权限:使用预设的短信全读全写,就够了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这样就得到了 SecretId 和 SecretKey

获取 SmsSdkAppId 和 TemplateId

去短信--> 应用管理--> 应用列表获取你的应用 id SmsSdkAppId 没有就新建一个
https://console.cloud.tencent.com/smsv2/app-manage
在这里插入图片描述
去短信--> 国内短信--> 正文模板管理 获取你审核通过的模板 id TemplateId 没有就新建一个等待审核通过
在这里插入图片描述

TxSmsServiceImpl.java 发送短信

package com.king.security.service;

import com.king.security.util.MyException;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @program: springboot
 * @description: 发送短信
 * @author: King
 * @create: 2022-03-17 15:12
 */
@Service
public class TxSmsServiceImpl {
    @Value(value = "${sendSms.SecretId}")
    private String secretId; //
    @Value(value = "${sendSms.SecretKey}")
    private String secretKey;
    @Value(value = "${sendSms.SmsSdkAppId}")
    private String SmsSdkAppId;
    @Value(value = "${sendSms.TemplateId}")
    private String TemplateId;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    //更改短信模板id
    public void setTemplateId(String templateId) {
        TemplateId = templateId;
    }

    /**
     * 发送短信
     *  @param phoneNumber 电话号码
     * @param smsCode     验证码
     * @return
     */
    public String sendSmsCode(String phoneNumber, String smsCode) throws MyException {
        try {
            Credential cred = new Credential(secretId, secretKey);
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("sms.tencentcloudapi.com");
            // 实例化一个client选项,可选的,没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            SendSmsRequest req = new SendSmsRequest();

            req.setPhoneNumberSet(new String[]{phoneNumber});
            req.setSmsSdkAppId(SmsSdkAppId);
            req.setTemplateId(TemplateId);
   			//SignName – 短信签名内容,使用 UTF-8 编码,必须填写已审核通过的签名,例如:腾讯云,
            // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 
            // 的签名管理查看。  发送国内短信该参数必填。 
            req.setSignName("花草信息个人网");
            //对应短信模板的内容 测试只支持数字字符串
            //您正在申请手机注册,验证码为:{1},{2}分钟内有效!
            String[] templateParamSet1 = {smsCode, "30"};
            req.setTemplateParamSet(templateParamSet1);

            // 返回的resp是一个SendSmsResponse的实例,与请求对象对应
            SendSmsResponse resp = client.SendSms(req);
            // 输出json格式的字符串回包
            logger.info(SendSmsResponse.toJsonString(resp));

            return resp.getSendStatusSet()[0].getMessage();
        } catch (TencentCloudSDKException e) {
            logger.error(e.toString());
            throw new MyException(e.getMessage());
        }

    }
}

CodeController.java 发送验证码

package com.king.security.controller;

import com.king.security.service.TxSmsServiceImpl;
import com.king.security.util.MyException;
import com.king.security.util.StringUtils;
import com.king.security.vo.ResultObj;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * @program: springboot
 * @description:
 * @author: King
 * @create: 2022-03-18 13:27
 */
@RestController
@PermitAll
@RequestMapping("/api/code")
@Api(value = "验证码接口", tags = "验证码接口")
public class CodeController {
    @Autowired
    private TxSmsServiceImpl txSmsService;

    @ApiOperation(value = "发送注册验证码", httpMethod = "POST")
    @ApiImplicitParam(name = "phone", value = "电话号码", dataType = "string", paramType = "query", example = "13788888888", required = true)
    @PostMapping("/sendSms.do")
    public ResultObj sendCodeRegister(String phone, HttpServletRequest request) {
        try {
            StringUtils.isPhone(phone);
            HttpSession session = request.getSession();
            Date lastDate = (Date) session.getAttribute("code_date");
            if (lastDate != null && (new Date().getTime() - lastDate.getTime()) < (1000 * 120)) {
                return ResultObj.error("别点了,等" + (120 - ((new Date().getTime() - lastDate.getTime()) / 1000)) + "秒后再点");
            } else {
                String code = StringUtils.getInt(6);
                session.setAttribute("code", code);//存验证码到session
                session.setAttribute("code_date", new Date());//存当前时间到session
                return ResultObj.ok(txSmsService.sendSmsCode(phone, code));
            }
        } catch (MyException e) {
            return ResultObj.error(e);
        }
    }
}

4、效果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、源码地址

Github https://github.com/KingJin-web/springboot

Gitee https://gitee.com/KingJin-web/springboot

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    943 引用 • 1460 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...