需求:浏览器端输入手机号,获取验证码。点击登录,验证验证码是否输入错误、是否超时等情况,一旦校验通过,将用户数据保存到数据中(业务逻辑)。

前提:注册阿里用户,开通短信服务,申请key、秘钥、签名、短信模板。参考:https://help.aliyun.com/document_detail/55284.html?spm=a2c4g.11174283.3.2.8d482c42qxWRYA

实现:

1、pom.xml文件添加阿里云短信服务的依赖

<!--阿里云短信发送start-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.0.</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.</version>
</dependency> <!--阿里云短信发送end-->

此处可能会报错,官网也说了,好像这个版本的不是很稳定吧。异常可能是:

Java.lang.NoClassDefFoundError:com/aliyuncs/exceptions/ClientException

  解决:

(1)方法一:检查lib文件下是否有aliyun-java-sdk-core包,没有的话就手动先添加上吧。

(2)方法二:将版本号改为3.3.1,即低版本

<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.3.</version>
</dependency>

2、下载官方demo,这个是发送短信的工具。

package com.alicom.dysms.api;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.dysmsapi.transform.v20170525.SendSmsResponseUnmarshaller;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile; import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID; /**
* 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
*/
public class SmsDemo { //产品名称:云通信短信API产品,开发者无需替换
static final String product = "Dysmsapi";
//产品域名,开发者无需替换
static final String domain = "dysmsapi.aliyuncs.com"; // TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
static final String accessKeyId = "yourAccessKeyId";
static final String accessKeySecret = "yourAccessKeySecret"; public static SendSmsResponse sendSms() throws ClientException { //可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "");
System.setProperty("sun.net.client.defaultReadTimeout", ""); //初始化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("");
//必填:短信签名-可在短信控制台中找到
request.setSignName("云通信");
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode("SMS_1000000");
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
request.setTemplateParam("{\"name\":\"Tom\", \"code\":\"123\"}"); //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
//request.setSmsUpExtendCode("90997"); //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
request.setOutId("yourOutId"); //hint 此处可能会抛出异常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); return sendSmsResponse;
} public static QuerySendDetailsResponse querySendDetails(String bizId) throws ClientException { //可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "");
System.setProperty("sun.net.client.defaultReadTimeout", ""); //初始化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("");
//可选-流水号
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 { //发短信
SendSmsResponse response = sendSms();
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 = querySendDetails(response.getBizId());
System.out.println("短信明细查询接口返回数据----------------");
System.out.println("Code=" + querySendDetailsResponse.getCode());
System.out.println("Message=" + querySendDetailsResponse.getMessage());
int i = ;
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());
} }
}

3、controller层

 /**
* app登录,附加:验证码时效性
* @param conditionStr
* @return
*/
@RequestMapping(value = "/anLogin", method = RequestMethod.POST)
@ResponseBody public ResponseModel anLogin(@RequestBody String conditionStr){
return androidLoginService.anLogin(conditionStr);
} /**
* 点击发送验证码
* @param conditionStr
* @return
*/
@RequestMapping(value = "/getVerificationCode", method = RequestMethod.POST)
@ResponseBody
public ResponseModel getVerificationCode(@RequestBody String conditionStr) {
return androidLoginService.getVerificationCode(conditionStr);
}

4、service实现层

package com.test.service.androidService.impl;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.test.dao.CarDriverMapper;
import com.test.entity.business.CarDriver;
import com.test.entity.common.ResponseModel;
import com.test.service.androidService.AndroidLoginService;
import com.test.service.common.impl.BaseServiceImpl;
import com.test.util.SessionUtil;
import com.test.util.SmsCodeUtil;
import com.test.util.SmsSendUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; @Service
public class AndroidLoginServiceImpl extends BaseServiceImpl implements AndroidLoginService {
public static final Logger logger = LoggerFactory.getLogger(AndroidLoginServiceImpl.class); @Resource
private CarDriverMapper carDriverMapper; @Override
public ResponseModel anLogin(String conditionStr) {
setResponseModel(new ResponseModel());
setErrorMsg("");
setSuccess(false);
Map<String,Object> resultMap = new HashMap<>();
try {
CarDriver carDriver = JSON.parseObject(conditionStr, CarDriver.class);
String tel_param = carDriver.getTel();
String verificationCode_param = carDriver.getVerificationCode();
//1-校验手机号和验证码不能为空
if(StringUtils.isBlank(tel_param)){
setErrorMsg("手机号不能为空!");
return getResponseModel();
}
if(StringUtils.isBlank(verificationCode_param)){
setErrorMsg("验证码不能为空!");
return getResponseModel();
}
//2-校验是否获取验证码
HttpSession session = SessionUtil.getRequest().getSession();
//获取session中登录手机号对应的验证码
Object verificationCode = session.getAttribute(tel_param);
if(verificationCode==null){
setErrorMsg("请先获取验证码!");
return getResponseModel();
}
//3-校验验证码是否相等
if(verificationCode_param.equals(verificationCode)){
//4-校验验证码是否过期(1*60s)
Object firstTime = session.getAttribute(tel_param+"Time");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
boolean bool = overtimeCode(firstTime.toString(),sdf.format(new Date()),*);
//bool等于true,则超时
if(!bool){
//5-业务逻辑
//5-1 校验手机号在数据库中是否存在
Integer id = this.carDriverMapper.selectByTel(carDriver);
if(id != null){
carDriver = this.carDriverMapper.selectByPrimaryKey(id);
resultMap.put("name",carDriver.getName());
}
else{
this.carDriverMapper.insertSelective(carDriver);
if(carDriver.getId() == null){
setErrorMsg("新增账号失败!");
throw new Exception(getErrorMsg());
}
}
resultMap.put("id",carDriver.getId());
resultMap.put("tel",carDriver.getTel());
resultMap.put("level",carDriver.getLevel());
setSuccess(true);
}else{
setErrorMsg("验证码获取超时,请重新获取!");
return getResponseModel();
}
}else{
setErrorMsg("验证码输入不正确!");
return getResponseModel();
}
}catch (Exception e){
e.printStackTrace();
logger.error(e.getMessage());
}finally {
getResponseModel().setData(resultMap);
getResponseModel().setSuccess(isSuccess());
getResponseModel().setErrorMsg(getErrorMsg());
}
return getResponseModel();
} @Override
public ResponseModel getVerificationCode(String conditionStr) {
setResponseModel(new ResponseModel());
setErrorMsg("");
setSuccess(false);
try {
CarDriver carDriver = JSON.parseObject(conditionStr, CarDriver.class);
//1-校验手机号不能为空
String tel = carDriver.getTel();
if(StringUtils.isBlank(tel)){
setErrorMsg("手机号不能为空!");
return getResponseModel();
}
//2-发送短信验证码
//生成随机码
String code = SmsCodeUtil.getRandom()+"";
//发送验证码
SendSmsResponse sendSmsResponse = SmsSendUtil.sendSms(carDriver.getTel(),"浏览器",code);
//如果发送成功则保存验证码和时间到session中
if(sendSmsResponse.getCode()!=null && sendSmsResponse.getCode().equals("OK")){
SessionUtil.getSession().setAttribute(tel, code);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SessionUtil.getSession().setAttribute(tel+"Time", sdf.format(new Date()));
//设置session最长存在时间60分钟
SessionUtil.getSession().setMaxInactiveInterval(*);
setSuccess(true);
} else{
setErrorMsg(sendSmsResponse.getMessage());
return getResponseModel();
}
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
}
finally {
getResponseModel().setErrorMsg(getErrorMsg());
getResponseModel().setSuccess(isSuccess());
}
return getResponseModel();
} /**
* 短信验证码有效期,如果true则过期了
* @param firstTime
* @param lastTime
* @param overtime
* @return
*/
private static boolean overtimeCode(String firstTime,String lastTime,long overtime){
boolean flag=false;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date one;
Date two;
try {
one = df.parse(firstTime);
two = df.parse(lastTime);
long time1 = one.getTime();
long time2 = two.getTime();
long diff = time2 - time1;
if(diff/>overtime){
flag=true;
}
} catch (ParseException e) {
e.printStackTrace();
}
return flag;
} }

附加:获取随机码工具类(我是投机取巧,拷贝腾讯云短信服务的demo中的)

package com.test.util;

import java.lang.StringBuffer;
import java.util.Random;
import java.util.ArrayList; import org.apache.commons.codec.digest.DigestUtils; public class SmsCodeUtil { public static boolean isNotEmpty(String s) {
if (s == null || s.isEmpty()){
return false;
}
return true;
} public static long getCurrentTime() {
return System.currentTimeMillis() / ;
} public static long getRandom() {
return (new Random(SmsCodeUtil.getCurrentTime())).nextInt() + ;
} public static String calculateSignature(String appkey, long random, long time,
String phoneNumber) { StringBuffer buffer = new StringBuffer("appkey=")
.append(appkey)
.append("&random=")
.append(random)
.append("&time=")
.append(time)
.append("&mobile=")
.append(phoneNumber); return sha256(buffer.toString());
} public static String calculateSignature(String appkey, long random, long time,
String[] phoneNumbers) { StringBuffer buffer = new StringBuffer("appkey=")
.append(appkey)
.append("&random=")
.append(random)
.append("&time=")
.append(time)
.append("&mobile="); if (phoneNumbers.length > ) {
buffer.append(phoneNumbers[]);
for (int i = ; i < phoneNumbers.length; i++) {
buffer.append(",");
buffer.append(phoneNumbers[i]);
}
} return sha256(buffer.toString());
} public static String calculateSignature(String appkey, long random, long time,
ArrayList<String> phoneNumbers) {
return calculateSignature(appkey, random, time, phoneNumbers.toArray(new String[]));
} public static String calculateSignature(String appkey, long random, long time) { StringBuffer buffer = new StringBuffer("appkey=")
.append(appkey)
.append("&random=")
.append(random)
.append("&time=")
.append(time); return sha256(buffer.toString());
} public static String calculateFStatusSignature(String appkey, long random,
long time, String fid) { StringBuffer buffer = new StringBuffer("appkey=")
.append(appkey)
.append("&random=")
.append(random)
.append("&time=")
.append(time)
.append("&fid=")
.append(fid); return sha256(buffer.toString());
} public static String calculateAuth(String appkey, long random, long time, String fileSha1Sum) {
StringBuffer buffer = new StringBuffer("appkey=")
.append(appkey)
.append("&random=")
.append(random)
.append("&time=")
.append(time)
.append("&content-sha1=")
.append(fileSha1Sum); return sha256(buffer.toString());
} public static String sha1sum(String rawString) {
return DigestUtils.sha1Hex(rawString);
} public static String sha1sum(byte[] bytes) {
return DigestUtils.sha1Hex(bytes);
} public static String sha256(String rawString) {
return DigestUtils.sha256Hex(rawString);
}
}

SessionUtil.java

package com.test.util;

import com.test.enums.SysConstants;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; /**
* Created by test on 2017/9/21.
*
*/
public class SessionUtil {
/**
* 清空session
*/
public static void cleanSession(){
Enumeration em = getSession().getAttributeNames();
while(em.hasMoreElements()){
getSession().removeAttribute(em.nextElement().toString());
}
}
/**
* 获取上一个访问连接
*/
public static String getBefUrl(){
Enumeration e = getRequest().getHeaders("Referer");
String befUrl;
if(e.hasMoreElements()){
befUrl = (String)e.nextElement();
}else{
befUrl = "";
}
return befUrl;
}
/**
* 获取request
*/
@SuppressWarnings("UnnecessaryLocalVariable")
public static HttpServletRequest getRequest() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); return request;
}
/**
* 获取response
*/
@SuppressWarnings("UnnecessaryLocalVariable")
public static HttpServletResponse getResponse() {
HttpServletResponse httpServletResponse = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); return httpServletResponse;
} /**
* 获取session
*/
public static HttpSession getSession() {
return getRequest().getSession();
} /**
* 验证是否重复提交
*/
public static boolean checkSubmitRepeat(String jspToken) {
String sessionToken = (String) getSession().getAttribute(SysConstants.SUBMITTOKEN.getName());
return StringUtils.isBlank(jspToken) || StringUtils.isBlank(sessionToken)||!sessionToken.equals(jspToken);
} }

特别注意的是,此处我们使用的是session保存验证码的格式,浏览器会自动保存sessionId,我们则方便获取。换做app的话,就不一样了,因为移动端没有sessionId,需要我们传输数据时候讲sessionId先传到移动端,再在登录时候,利用移动端传输过来的sessionId获取目标session的值。下节出代码。

浏览器端获取短信验证码java实现——阿里云短信服务的更多相关文章

  1. 移动端获取短信验证码java实现——阿里云短信服务

    需求:移动端输入手机号,获取验证码.点击登录,验证验证码是否输入错误.是否超时等情况,一旦校验通过,将用户数据保存到数据中(业务逻辑). 前提:注册阿里用户,开通短信服务,申请key.秘钥.签名.短信 ...

  2. java实现阿里云短信服务发送验证码

    由于做项目的时候遇到了接第三方短信服务,所以记录一下. 一.新建一个maven项目并导入相关依赖 <!--手机发送短信验证码--> <dependency> <group ...

  3. Java调用阿里云短信接口发送手机验证码

    前五步可参考阿里云服务文档:https://help.aliyun.com/document_detail/59210.html?spm=a2c4g.11174283.4.1.2b152c42DoJ7 ...

  4. Java调用阿里云短信通道服务【千锋】

    这里我们使用SpringBoot 来调用阿里通信的服务. 阿里通信,双11.收到短信,日发送达6亿条.保障力度非常高. 使用的步骤: 1.1. 第一步:需要开通账户 1.2. 第二步:阅读接口文档 1 ...

  5. 零基础大数据入门教程:Java调用阿里云短信通道服务

    这里我们使用SpringBoot 来调用阿里通信的服务. 阿里通信,双11.收到短信,日发送达6亿条.保障力度非常高. 使用的步骤: 1.1. 第一步:需要开通账户 1.2. 第二步:阅读接口文档 1 ...

  6. JAVA调用阿里云短信接口

    官方文档:https://help.aliyun.com/document_detail/101414.html?spm=a2c4g.11186623.6.626.2cef6220yxh5l7 jar ...

  7. Java 使用阿里云短信的API接口

    亲们上午好,写的不好的地方还望指正.谢谢各位! 引言 短信服务(Short Message Service)是阿里云为用户提供的一种通信服务的能力,支持快速发送短信验证码.短信通知等.(我这里只讲一个 ...

  8. java 调用阿里云短信接口,报InvalidTimeStamp.Expired : Specified time stamp or date value is expired.

    官网解释: 问题所在: 自己的电脑(或者服务器) 的时间与阿里云的服务器时间 相差15分钟了. 解决方法 : 把自己的电脑时间 (或者服务器)的时间 改成标准的北京时间就行了.

  9. php 阿里云短信验证码

    阿里云短信服务:https://dysms.console.aliyun.com 1.准备 1.1.创建签名.模板 1.2.创建.使用阿里云秘钥 地址:https://usercenter.conso ...

随机推荐

  1. 防盗链测试01 - Jwplayer+Tengine2.3.1 mp4模块打造流媒体测试服务器

    最近有个想法,想做类似下面的视频URL验证: 1.URL Tag Validation 2.Special format of URL for preventing unauthorized usag ...

  2. js的真值与假值

    假值 结果为 false 的值称为 假值.例如,空字符串 "" 为假值,因为在布尔表达式中,"" 等于 false. false == 0返回:true fal ...

  3. Oracle - View

    Oracle View的创建 Create Or Replace View ViewName As Select * From Tables/View Where 条件;

  4. 利用Spring Boot+zxing,生成二维码还能这么简单

    在网站开发中,经常会遇到要生成二维码的情况,比如要使用微信支付.网页登录等,本文分享一个Spring Boot生成二维码的例子,这里用到了google的zxing工具类. 本文目录 一.二维码简介二. ...

  5. CentOS7下使用SonatypeNexus3搭建Docker私有仓库

    前置条件:安装docker(如果机器上没有安装的话) //安装一些必要的系统工具: sudo yum install -y yum-utils device-mapper-persistent-dat ...

  6. CodeForces - 534B-Covered Path+思路

    CodeForces - 534B 题意:给定初始和末尾的速度,和最大加速度和总时间,求出走的最长路程: 我一开始以为代码写起来会很繁琐... #include <iostream> #i ...

  7. lightoj 1201 - A Perfect Murder(树形dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1201 题解:简单的树形dp,dp[0][i]表示以i为根结点不傻i的最多有多少 ...

  8. Charles安装windows篇

    简介 Charles是一款非常好用的网络抓包工具,类似fiddle抓包工具,当然也可以理解为一款HTTP代理服务器.HTTP监视器.反向代理服务器等. 二.官网下载 地址:https://www.ch ...

  9. centos 6.5 系统故障分析实验

    系统故障分析实验 日志文件分析 日志的功能 用于记录系统.程序运行中发生的各种事件 通过阅读日志,有助于诊断和解决系统故障 日志文件的分类 内核及系统日志 由系统服务syslog统一进行管理,日志格式 ...

  10. 为什么说 Java 程序员必须掌握 Spring Boot ?(转)

    Spring Boot 2.0 的推出又激起了一阵学习 Spring Boot 热,那么, Spring Boot 诞生的背景是什么?Spring 企业又是基于什么样的考虑创建 Spring Boot ...