当前位置: 首页 > news >正文

2023-01-16 阿里SMS短信接口使用

用户注册—使用阿里短信接口和Redis

文章目录

  • 用户注册—使用阿里短信接口和Redis
      • 步骤
      • 1.导入依赖
      • 2.redis属性配置文件
      • 3.spring集成redis配置文件
      • 4.短信接口属性配置文件
      • 5.短信接口核心配置类
      • 6.对应的Service层
      • 7.对应的Controller层

步骤

1.用户注册时,在注册页填写手机号进行手机验证码的获取

2.后台收到验证码请求后,首先校验手机号是否已存在

3.若手机号存在,则提醒用户。

4.若不存在,生成验证码,调用短信接口进行验证码发送

5.判断验证码发送是否成功,成功后将用户手机号作为key,验证码作为value存到redis中,并设置redis的key的有效时间为15分钟。来使验证码只有15分钟内有效

6.成功后用户输入信息,判断用户名是否重复。

7.校验完成后提交表单,使用表单数据与redis中手机号对应的数值判断验证码是否正确,进行注册。

1.导入依赖

短信依赖

   <!-- 阿里短信 -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.0.6</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
            <version>1.1.0</version>
        </dependency>

redis依赖


        <!-- redis -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.6.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.3</version>
        </dependency>
        
         <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>1.2.1.RELEASE</version>
        </dependency>

2.redis属性配置文件

#redis\u4E2D\u5FC3
#\u7ED1\u5B9A\u7684\u4E3B\u673A\u5730\u5740
redis.host=192.168.25.100
#\u6307\u5B9ARedis\u76D1\u542C\u7AEF\u53E3\uFF0C\u9ED8\u8BA4\u7AEF\u53E3\u4E3A6379
redis.port=6379
#\u6388\u6743\u5BC6\u7801\uFF08\u53EF\u4EE5\u4E0D\u4F7F\u7528\uFF09
#redis.password=bjtu
#\u6700\u5927\u7A7A\u95F2\u6570\uFF1A\u7A7A\u95F2\u94FE\u63A5\u6570\u5927\u4E8EmaxIdle\u65F6\uFF0C\u5C06\u8FDB\u884C\u56DE\u6536
redis.maxIdle=100
#\u6700\u5927\u8FDE\u63A5\u6570\uFF1A\u80FD\u591F\u540C\u65F6\u5EFA\u7ACB\u7684\u201C\u6700\u5927\u94FE\u63A5\u4E2A\u6570\u201D
redis.maxTotal=200
#\u6700\u5927\u7B49\u5F85\u65F6\u95F4\uFF1A\u5355\u4F4Dms
redis.maxWait=1000
#\u4F7F\u7528\u8FDE\u63A5\u65F6\uFF0C\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6210\u529F 
redis.testOnBorrow=false
#\u5F53\u5BA2\u6237\u7AEF\u95F2\u7F6E\u591A\u957F\u65F6\u95F4\u540E\u5173\u95ED\u8FDE\u63A5\uFF0C\u5982\u679C\u6307\u5B9A\u4E3A0\uFF0C\u8868\u793A\u5173\u95ED\u8BE5\u529F\u80FD
redis.timeout=10000

redis.prefix=redis:cache:

3.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:context="http://www.springframework.org/schema/context"
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
	   xmlns:p="http://www.springframework.org/schema/p"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xmlns:task="http://www.springframework.org/schema/task"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:cache="http://www.springframework.org/schema/cache"
	   xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	   xmlns:redis="http://www.springframework.org/schema/redis"
	   xsi:schemaLocation="http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.1.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
		http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
		http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis-1.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

	<context:component-scan base-package="com.li">
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>


	<context:property-placeholder location="classpath:redis.properties,classpath:db.properties" ignore-resource-not-found="true" ignore-unresolvable="true"/>

	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWait}" />
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
		<property name="maxTotal" value="${redis.maxTotal}" />
		<property name="blockWhenExhausted" value="true" />
	</bean>

	<!-- jedis连接工程的配置 -->
	<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="${redis.host}" />
		<property name="port" value="${redis.port}" />
		<property name="poolConfig" ref="jedisPoolConfig" />
		<!-- <property name="password" value="${redis.password}" /> -->
		<property name="usePool" value="true"/>
		<property name="timeout" value="${redis.timeout}"></property>
	</bean>

	<!-- redisTemplate配置 -->
	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory"   ref="jedisConnectionFactory" />
		<property name="keySerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="valueSerializer">
			<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
		</property>
		<property name="hashKeySerializer">
			<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
		</property>
		<property name="hashValueSerializer">
			<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
		</property>
	</bean>




	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="user" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="initialPoolSize" value="${connection_pools.initial_pool_size}" />
		<property name="minPoolSize" value="${connection_pools.min_pool_size}" />
		<property name="maxPoolSize" value="${connection_pools.max_pool_size}" />
		<property name="maxIdleTime" value="${connection_pools.max_idle_time}" />
		<property name="acquireIncrement" value="${connection_pools.acquire_increment}" />
		<property name="checkoutTimeout" value="${connection_pools.checkout_timeout}" />
	</bean>

	<!-- 配置MyBatis的sqlSession -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- <property name="configLocation" value="classpath:mybatis.xml"></property> -->
		<property name="dataSource" ref="dataSource" />
		<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
	</bean>

	<!-- 事务管理器 -->
	<bean id="transactionManager"
		  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<!-- xml  aop事物方式 -->
	<aop:config>
		<!-- 切入点 -->
		<aop:pointcut expression="execution (* com.li.service.*.*(..))" id="serviceMethodAOP"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethodAOP"/>
	</aop:config>


	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- 方法名称 以  add加入事物处理    addGoods  updateGoods-->
			<tx:method name="insert*" propagation="REQUIRED" rollback-for="RunTimeException"/>
			<tx:method name="update*" propagation="REQUIRED" rollback-for="RunTimeException"/>
			<tx:method name="delete*" propagation="REQUIRED" rollback-for="RunTimeException"/>
			<tx:method name="get*" propagation="NOT_SUPPORTED" rollback-for="RunTimeException" read-only="true"/>
			<tx:method name="select*" propagation="NOT_SUPPORTED" rollback-for="RunTimeException" read-only="true"/>
			<tx:method name="find*" propagation="NOT_SUPPORTED" rollback-for="RunTimeException" read-only="true"/>
		</tx:attributes>
	</tx:advice>


	<!-- 映射Mapper目录 -->
	<!-- Mapper接口所在包名,Spring会自动查找其下的Mapper -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.li.mapper" />
	</bean>
	<!-- <bean id="sessionUtils" class="com.oracle.utils.SessionUtils"></bean> -->
</beans>

4.短信接口属性配置文件

sms.product   =Dysmsapi
sms.domain   =dysmsapi.aliyuncs.com
sms.accessKeyId   =xxx
sms.accessKeySecret   =xxx
sms.templateCode   =SMS_xxx

5.短信接口核心配置类

/**
 * Created on 17/6/7.
 * 短信API产品的DEMO程序,工程中包含了一个SmsDemo类,直接通过
 * 执行main函数即可体验短信产品API功能(只需要将AK替换成开通了云通信-短信产品功能的AK即可)
 * 工程依赖了2个jar包(存放在工程的libs目录下)
 * 1:aliyun-java-sdk-core.jar
 * 2:aliyun-java-sdk-dysmsapi.jar
 *
 * 备注:Demo工程编码采用UTF-8
 * 国际短信发送请勿参照此DEMO
 */
@Configuration
@PropertySource("classpath:sms.properties")
public class SmsConfig {

    @Value("${sms.product}")
    private String product;
    @Value("${sms.domain}")
    private String domain;

    @Value("${sms.accessKeyId}")
    private String accessKeyId;
    @Value("${sms.accessKeySecret}")
    private String accessKeySecret;
    @Value("${sms.templateCode}")
    private String templateCode;
    @Value("Poseidon管理中心")
    private String signName;


    public SendSmsResponse sendSms(String phone,String randomCode) throws ClientException {
        try {
            //可自助调整超时时间
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");

            //初始化acsClient,暂不支持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();
            //必填:待发送手机号
            request.setPhoneNumbers(phone);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName(signName);
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(templateCode);
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            request.setTemplateParam("{\"code\":"+randomCode+"}");

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

            //hint 此处可能会抛出异常,注意catch
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
            return sendSmsResponse;
        } catch (ClientException e) {
            throw e;
        }

    }


    public  QuerySendDetailsResponse querySendDetails(String bizId) throws ClientException {

        //可自助调整超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");

        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象
        QuerySendDetailsRequest request = new QuerySendDetailsRequest();
        //必填-号码
        request.setPhoneNumber("138xxxxxxxx");
        //可选-流水号
        request.setBizId(bizId);
        //必填-发送日期 支持30天内记录查询,格式yyyyMMdd
        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
        request.setSendDate(ft.format(new Date()));
        //必填-页大小
        request.setPageSize(10L);
        //必填-当前页码从1开始计数
        request.setCurrentPage(1L);

        //hint 此处可能会抛出异常,注意catch
        QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);

        return querySendDetailsResponse;
    }

   public static void main(String[] args) throws ClientException, InterruptedException {
        SmsConfig smsConfig = new SmsConfig();
        //发短信
        SendSmsResponse response = smsConfig.sendSms("xxxxxx","xxx");
        System.out.println("短信接口返回的数据----------------");
        System.out.println("Code=" + response.getCode());
        System.out.println("Message=" + response.getMessage());
        System.out.println("RequestId=" + response.getRequestId());
        System.out.println("BizId=" + response.getBizId());

        Thread.sleep(3000L);

        //查明细
        if(response.getCode() != null && response.getCode().equals("OK")) {
            QuerySendDetailsResponse querySendDetailsResponse = smsConfig.querySendDetails(response.getBizId());
            System.out.println("短信明细查询接口返回数据----------------");
            System.out.println("Code=" + querySendDetailsResponse.getCode());
            System.out.println("Message=" + querySendDetailsResponse.getMessage());
            int i = 0;
            for(QuerySendDetailsResponse.SmsSendDetailDTO smsSendDetailDTO : querySendDetailsResponse.getSmsSendDetailDTOs())
            {
                System.out.println("SmsSendDetailDTO["+i+"]:");
                System.out.println("Content=" + smsSendDetailDTO.getContent());
                System.out.println("ErrCode=" + smsSendDetailDTO.getErrCode());
                System.out.println("OutId=" + smsSendDetailDTO.getOutId());
                System.out.println("PhoneNum=" + smsSendDetailDTO.getPhoneNum());
                System.out.println("ReceiveDate=" + smsSendDetailDTO.getReceiveDate());
                System.out.println("SendDate=" + smsSendDetailDTO.getSendDate());
                System.out.println("SendStatus=" + smsSendDetailDTO.getSendStatus());
                System.out.println("Template=" + smsSendDetailDTO.getTemplateCode());
            }
            System.out.println("TotalCount=" + querySendDetailsResponse.getTotalCount());
            System.out.println("RequestId=" + querySendDetailsResponse.getRequestId());
        }

    }
}

6.对应的Service层

@Service
public class MemberService {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private MemberMapper memberMapper;
    @Value("${redis.prefix}")
    private String redisCache;



    /**
     * 校验手机号是否重复
     * @return
     */
    public boolean checkPhone(String phone){
        MemberExample memberExample = new MemberExample();
        MemberExample.Criteria criteria = memberExample.createCriteria();
        criteria.andPhoneEqualTo(phone);
        int count = memberMapper.countByExample(memberExample);
        return count==0;
    }

    /**
     * 存验证码到redis
     * @return
     */
    public void cachePhone(String phone,String randomCode){

        String redisKey = redisCache+"reg:member:"+phone;
        //存redis
        redisTemplate.boundValueOps(redisKey).set(randomCode,2, TimeUnit.MINUTES);

    }

    /**
     * 校验短信验证码
     * @return
     */
    public boolean checkSmsCode(String smsCode,String phone){
        String redisKey = redisCache+"reg:member:"+phone;
        String code = redisTemplate.boundValueOps(redisKey).get();
        if(code==null||!code.equals(smsCode)){
            return false;
        }
        return true;
    }

    /**
     * 注册
     */
    public void memberReg(Member memberVo){
        memberVo.setStatus(200);
        memberMapper.insertSelective(memberVo);
    }

    /**
     * 校验用户名
     */
    public boolean checkUsername(String username){
        MemberExample memberExample = new MemberExample();
        MemberExample.Criteria criteria = memberExample.createCriteria();
        criteria.andUsernameEqualTo(username);
        int count = memberMapper.countByExample(memberExample);
        return count==0;
    }
}

7.对应的Controller层


@Slf4j
@Controller
@RequestMapping("member")
public class MemberController {

    @Autowired
    private MemberService memberService;
    @Autowired
    private SmsConfig smsConfig;

    @RequestMapping("/getMobileCode")
    @ResponseBody
    public R getMobilePhone(String phone) throws ClientException {
        log.info("获取手机验证码开始,手机号:{0}",phone);
        boolean flag = memberService.checkPhone(phone);
        if(flag){
            //验证码
            String code = RandomCodeUtils.createRegisterCode().toString();
            SendSmsResponse response = null;
            try {
                //发送短信验证码
                response = smsConfig.sendSms(phone, code);
                if(response.getCode() != null && response.getCode().equals("OK")) {
                    //存redis
                    memberService.cachePhone(phone,code);
                    return new R(200,"验证码已发送",null);
                }
            } catch (Exception e) {
                    QuerySendDetailsResponse querySendDetailsResponse = smsConfig.querySendDetails(response.getBizId());
                    System.out.println("短信明细查询接口返回数据----------------");
                    System.out.println("Code=" + querySendDetailsResponse.getCode());
                    System.out.println("Message=" + querySendDetailsResponse.getMessage());
                    e.printStackTrace();
                    return new R(400, querySendDetailsResponse.getMessage(), null);

            }
        }
        return new R(400,"手机号已存在",null);
    }

    /**
     * 用户注册
     * @param smsCode
     * @return
     */
    @RequestMapping("/register")
    public String memberReg(Member memberVo, String smsCode, Model model){
        //校验短信验证码是否正确
        boolean flag = memberService.checkSmsCode(smsCode, memberVo.getPhone());
        if(flag){
            //验证成功,进行注册
            memberService.memberReg(memberVo);
            return "reg_success";
        }
        model.addAttribute("info","手机验证码错误,注册失败");
        return "reg";
    }

    @RequestMapping("/checkUsername")
    @ResponseBody
    public R checkUsername(String username){
        boolean flag = memberService.checkUsername(username);
        if(flag){
            return new R(200,"用户名可用",null);
        }
        return new R(400,"用户名已存在",null);
    }
}

相关文章:

  • 中财盛建设集团公司网站/网站模板购买
  • 网店erp系统哪个好/怎样进行seo推广
  • 做网站需要会语言吗/搜索引擎排名优化建议
  • wordpress geek theme/app拉新接单平台
  • 腾讯今日头条新闻最新/qq群排名优化软件购买
  • 肥城做网站/正规的计算机培训机构
  • 【linux kernel】Linux设备驱动模型 | bus
  • HTML的body元素
  • Spring Boot(五十四):SpringBoot事件监听机制
  • Fastdfs分布式文件系统原理浅析
  • 3-2存储系统-主存与CPU的连接外部存储器
  • 20230116英语学习
  • 质量体系搭建
  • PAT2.7 弹球距离
  • 华为机试题:HJ13 句子逆序(python)
  • spring学习系列
  • Pytorch模型自定义数据集训练流程
  • 云原生技术学习笔记(基础版)