首页 > 技术文章 > 用阿里云发送验证码使用步骤以及验证码后台校验思路

qianyi525 2020-10-17 18:19 原文

一、阿里云短信服务使用介绍

  1、登录阿里云官网,找到短信服务,选择签名管理

 

 

   2、添加签名,如何添加自己看就可以了,很简单,签名内容就是发送短信内容的第一句话,这里注意的就是通用签名现在只有公司才能用,个人只能用验证码签名

 

 

   3、除了签名以外,还要添加短息模板,我们将通过代码方式调用工具类,传入签名、短信模板、手机号来发送验证码,模板可以用自动生成的

 

 

   4、在发送短信时需要进行身份认证,只有认证通过才能发送短信,所以还需要在阿里云的右上角点击用户,获取密钥

  5、无论你选则下面哪个都行,我们选择子用户,指定用户权限,而不是分配所有权限。

 

 

   6、我们要点击编程访问

 

 

   7、新建用户成功后要进行授权,自己找找,懒得放图片了,找到创建的用户就能看到授权两个字了

   8、给新建的用户添加权限内容,搜索一下短信服务,两个都点上

   9、然后就生成密钥,就是要注意,因为是点击的编程访问,所以密钥一定要记得复制然后保存,因为只会出现这一次,以后再也不会出现(我说的密钥就是下图的KeyID和KeySecret)

 

 

 

    10、最后记得,这个服务要钱的,只不过不贵就是了

  11、java使用短信验证码api在官网上就能找到,用户指南啥的,懒得去看了,我直接把我改了下的工具类放在这吧

/**
 * 阿里云短信验证工具类
 * */
public class AliSNMUtil {
    public static final String TEMPLET_IDENTIFYING ="SMS_20475xxxx";//发送验证码的模板

    /**
     *
     * 发送短信验证码
     * phone:发送给哪个电话号码,需传入
     * identifyingCode:发送的验证码内容
     * templet:传入短信模板,阿里云里面有
     */
    public static void sendVerification(String phone,Object identifyingCode,String templet) throws ClientException {
        //设置超时时间-可自行调整
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
        //初始化ascClient需要的几个参数
        final String product = "Dysmsapi";//短信API产品名称(短信产品名固定,无需修改)
        final String domain = "dysmsapi.aliyuncs.com";//短信API产品域名(接口地址固定,无需修改)
        //替换成你的AK
        final String accessKeyId = "xxxxxxxxxxxxxxxxxxx";//你的accessKeyId,参考本文档步骤2
        final String accessKeySecret = "xxxxxxxxxxxxxxxx";//你的accessKeySecret,参考本文档步骤2
        //初始化ascClient,暂时不支持多region(请勿修改)
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,
                accessKeySecret);
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象
        SendSmsRequest request = new SendSmsRequest();
        //使用post提交
        request.setMethod(MethodType.POST);
        //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为国际区号+号码,如“85200000000”
        request.setPhoneNumbers(phone);
        //必填:短信签名-可在短信控制台中找到
        request.setSignName("ABC商城");
        //必填:短信模板-可在短信控制台中找到,发送国际/港澳台消息时,请使用国际/港澳台短信模版
        request.setTemplateCode(templet);
        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
//参考:request.setTemplateParam("{\"变量1\":\"值1\",\"变量2\":\"值2\",\"变量3\":\"值3\"}")
        request.setTemplateParam("{\"code\":\""+identifyingCode+"\"}");
        //可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
        //request.setSmsUpExtendCode("90997");

        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
        request.setOutId("yourOutId");

//请求失败这里会抛ClientException异常
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
        if(sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
//请求成功
            System.out.println("发送成功!");
        }

    }
}

 

  12、但是,你只复制了一个工具类,肯定满篇报错满篇红,别急,依赖都没加,玩个屁啊

<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>aliyun-java-sdk-core</artifactId>
  <version>3.3.1</version>
</dependency>
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
  <version>1.0.0</version>
</dependency>

 

 

二、验证码校验思路

    在项目中,你要发验证码简单,但你得校验啊,不是一哆嗦把短信发了然后就提裤子走人,你得负责啊,别人把验证码输入了,你怎么确定他输入正确呢?

    思路非常简单的,直接在redis中保存就好了,用收验证码的手机号码做key,用验证码内容做值,存储五分钟,发验证码之前先在redis中存储一份,提交表单后拿输入的验证码跟redis中的验证码匹配一下就知道对不对了。步骤搞起来:

  1、因为要用到redis,所以还得加redis依赖,下面就不细分步骤了,直接跟着一步步来就可以

 

依赖:我没有指定版本号,自己选择比较好

<dependencies>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定端口 -->
                    <port>84</port>
                    <!-- 请求路径 -->
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>

配置applicationContext-redis.xml,spring整合redis

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/mvc
                         http://www.springframework.org/schema/mvc/spring-mvc.xsd
                        http://code.alibabatech.com/schema/dubbo
                         http://code.alibabatech.com/schema/dubbo/dubbo.xsd
                        http://www.springframework.org/schema/context
                         http://www.springframework.org/schema/context/spring-context.xsd">

    <!--Jedis连接池的相关配置-->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal">
            <value>200</value>
        </property>
        <property name="maxIdle">
            <value>50</value>
        </property>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
    </bean>
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="127.0.0.1" />
        <constructor-arg name="port" value="6379" type="int" />
        <constructor-arg name="timeout" value="30000" type="int" />
    </bean>
</beans>

日志文件,log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

配置web.xml,启动加载spring容器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">
    <display-name>Archetype Created Web Application</display-name>
    <!-- 加载spring容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>      <!-- 下面的两个 * ,前面一个表示当前工程依赖的工程里面如果有相同文件名的配置,也会被当前工程加载                  后面一个表示这个文件名后面无论是什么,都会被这个工程加载进来                  这里前面一个*可以不用,后面那个得要,因为我要加载两个配置文件,如果不加的话,需要在其中一个配置文件中引入另一个配置文件-->
        <param-value>classpath*:applicationContext*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

 

这样创建的工程环境应该就没有问题了,如果出现什么爆红什么的,自己动动手看看什么情况吧,可能是格式错误

 

  2、现在开始调用工具类发送验证码,并将验证码存入redis中

/**
 * 发送验证码
 * */public class Test001{
/**
     * 发送验证码
     * */
@Test
public static void main test02(){ try { //生成验证码,我用的是工具类,RandomizationUtil,在我的小工具分类的随笔中有 Integer identifyingCode = (RandomizationUtil.generateValidateCode(6)); //将验证码存入redis五分钟,第一个参数是电话号,第二个是在redis中存多久,单位是秒,第三个是生成的验证码 jedisPool.getResource().setex(13117499999,60*5,identifyingCode.toString()); //调用方法发送短信,参数去看发送验证码的工具类就行了,在上面 AliSNMUtil.sendVerification(13117499999,identifyingCode.toString(),ALiSNMUtil.TEMPLET_IDENTIFYING); return new Result(true,"验证码发送成功"); } catch (ClientException e) { e.printStackTrace(); return new Result(true,"验证码发送失败"); } } }

  3、从redis中取验证码比较,上面这段代码和下面这段代码不要拷贝,因为我是从自己项目中拷贝出来的,随意修改,只需要看用了什么方法就行了,代码不多

//校验验证码是否正确,第一行代码是操作redis,根据key获取值,第二行代码是从map中获取用户输入的验证码,第三行就是判断了
        String redisVerificationCode = jedisPool.getResource().get(telephone);
        String validateCode = (String) map.get("validateCode");
        if (StringUtils.isEmpty(redisVerificationCode)|| StringUtils.isEmpty(validateCode)||!redisVerificationCode.equals(validateCode)) {
                return new Result(false, MessageConstant.VALIDATECODE_ERROR);
        

 

推荐阅读