在网页上我们经常见到有短信验证的功能,他是如何实现的呢?

需要的技术:

  1. springboot后端
  2. HttpClientUtils工具类
    该类是帮助连接其它网站的一个工具类,现在已经出到了第三个版本(后面会放源码)
  3. json解析等依赖,xml解析依赖

前期准备

  1. 京东万象网址:https://wx.jdcloud.com/market/datas/5/10306
    这里我选择使用106短信接口,每个人有8次免费使用的机会
  2. 首先查看一下这个短信的参数要求

    已经十分明确,主要需要你的appkey(每人都不一样,京东万象提供的)
    手机号:前端传递
    短信内容:后端生成随机数并字符串拼接
  3. 再看返回参数:

可以看到主要有两部分成,一部分是京东万象的回馈code,另一部分是106接口的返回值,106接口的返回值是xml类型,京东万象的返回值是json类型
返回值实例:

{"code": "10000","charge": false,"remain": 0,"msg": "查询成功","result": "<?xml version=\"1.0\" encoding=\"utf-8\" ?><returnsms>\n <returnstatus>Success</returnstatus>\n <message>ok</message>\n <remainpoint>-1111611</remainpoint>\n <taskID>101609164</taskID>\n <successCounts>1</successCounts></returnsms>"
}

就是这个样子,前一部分为json,后一部分为xml
好,现在已经弄明白了都有啥,那就开始

项目开始

pom.xml导入依赖

<!-- httpclient4.5.3版本 --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.36</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency>

导入HttpClientUtils.java

package com.springboot.utils;import com.alibaba.fastjson .JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.*;/*** ClassName:HttpClientUtils* Package:com.bjpowernode.p2p.common.util.http* Description:<br/>* @author:郭鑫* @email:41700175@qq.com*/
public class HttpClientUtils {/*** 编码格式。发送编码格式统一用UTF-8*/private static final String ENCODING = "UTF-8";/*** 设置连接超时时间,单位毫秒。*/private static final Integer CONNECT_TIMEOUT = 6000;/*** 请求获取数据的超时时间(即响应时间),单位毫秒。*/private static final Integer SOCKET_TIMEOUT = 6000;/*** 发送get请求;不带请求头和请求参数** @param url 请求地址* @return* @throws Exception*/public static String doGet(String url) throws Exception {return doGet(url, null, null);}/*** 发送get请求;带请求参数** @param url    请求地址* @param params 请求参数集合* @return* @throws Exception*/public static String doGet(String url, Map<String, String> params) throws Exception {return doGet(url, null, params);}/*** 发送get请求;带请求头和请求参数** @param url     请求地址* @param headers 请求头集合* @param params  请求参数集合* @return* @throws Exception*/public static String doGet(String url, Map<String, String> headers, Map<String, String> params) throws Exception {// 创建httpClient对象CloseableHttpClient httpClient = HttpClients.createDefault();// 创建访问的地址URIBuilder uriBuilder = new URIBuilder(url);if (params != null) {Set<Map.Entry<String, String>> entrySet = params.entrySet();for (Map.Entry<String, String> entry : entrySet) {uriBuilder.setParameter(entry.getKey(), entry.getValue());}}// 创建http对象HttpGet httpGet = new HttpGet(uriBuilder.build());/*** setConnectTimeout:设置连接超时时间,单位毫秒。* setConnectionRequestTimeout:设置从connect Manager(连接池)获取Connection* 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。* setSocketTimeout:请求获取数据的超时时间(即响应时间),单位毫秒。* 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。*/RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();httpGet.setConfig(requestConfig);// 设置请求头packageHeader(headers, httpGet);// 创建httpResponse对象CloseableHttpResponse httpResponse = null;//响应结果String result = "";try {// 执行请求httpResponse = httpClient.execute(httpGet);// 获取返回结果if (httpResponse != null && httpResponse.getStatusLine() != null) {if (httpResponse.getEntity() != null) {result = EntityUtils.toString(httpResponse.getEntity(), ENCODING);}}} finally {// 释放资源release(httpResponse, httpClient);}return result;}/*** 发送post请求;不带请求头和请求参数** @param url 请求地址* @return* @throws Exception*/public static String doPost(String url) throws Exception {return doPost(url, null, null);}/*** 发送post请求;带请求参数** @param url    请求地址* @param params 参数集合* @return* @throws Exception*/public static String doPost(String url, Map<String, Object> params) throws Exception {return doPost(url, null, params);}/*** 发送post请求;带请求头和请求参数** @param url     请求地址* @param headers 请求头集合* @param params  请求参数集合* @return* @throws Exception*/public static String doPost(String url, Map<String, String> headers, Map<String, Object> params) throws Exception {// 创建httpClient对象CloseableHttpClient httpClient = HttpClients.createDefault();// 创建http对象HttpPost httpPost = new HttpPost(url);/*** setConnectTimeout:设置连接超时时间,单位毫秒。* setConnectionRequestTimeout:设置从connect Manager(连接池)获取Connection* 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。* setSocketTimeout:请求获取数据的超时时间(即响应时间),单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。*/RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();httpPost.setConfig(requestConfig);// 设置请求头/*httpPost.setHeader("Cookie", "");httpPost.setHeader("Connection", "keep-alive");httpPost.setHeader("Accept", "application/json");httpPost.setHeader("Accept-Language", "zh-CN,zh;q=0.9");httpPost.setHeader("Accept-Encoding", "gzip, deflate, br");httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");*/packageHeader(headers, httpPost);// 封装请求参数packageParam(params, httpPost);// 创建httpResponse对象CloseableHttpResponse httpResponse = null;String result = "";try {// 执行请求httpResponse = httpClient.execute(httpPost);// 获取返回结果if (httpResponse != null && httpResponse.getStatusLine() != null) {if (httpResponse.getEntity() != null) {result = EntityUtils.toString(httpResponse.getEntity(), ENCODING);}}} finally {// 释放资源release(httpResponse, httpClient);}return result;}/*** @Title:POST请求* @Decription:发送POST请求,data参数只支持JSON对象(com.alibaba.fastjson.JSONObject)* @param url  请求地址* @param data 只支持JSON对象(com.alibaba.fastjson.JSONObject)* @return String*/public static String sendPost(String url, JSONObject data) throws IOException {// 设置默认请求头Map<String, String> headers = new HashMap<>();headers.put("content-type", "application/json");return doPostByJSON(url, headers, data, ENCODING);}/*** @Title:POST请求* @param url    请求地址* @param params Map集合(输入参数要求为JSON对象)* @return String*/public static String sendPost(String url, Map<String, Object> params) throws IOException {// 设置默认请求头Map<String, String> headers = new HashMap<>();headers.put("Content-Type", "application/json");// 将map转成jsonJSONObject data = JSONObject.parseObject(JSON.toJSONString(params));return doPostByJSON(url, headers, data, ENCODING);}/*** @Title POST请求* @param url     请求地址* @param headers Map集合的请求头信息* @param data    只支持JSON对象(com.alibaba.fastjson.JSONObject)* @return String*/public static String sendPost(String url, Map<String, String> headers, JSONObject data) throws IOException {return doPostByJSON(url, headers, data, ENCODING);}/*** @Title POST请求(默认编码:UTF-8)* @param url     请求地址* @param headers Map集合的请求头参数* @param params  Map集合(输入参数为JSON对象)* @return String*/public static String sendPost(String url, Map<String, String> headers, Map<String, String> params) throws IOException {// 将map转成jsonJSONObject data = JSONObject.parseObject(JSON.toJSONString(params));return doPostByJSON(url, headers, data, ENCODING);}/*** @Title: sendPost* @Description: TODO(发送post请求)* @author 郭鑫* @date 2018年5月10日 下午4:36:17* @param url      请求地址* @param headers  请求头* @param data     请求实体* @param encoding 字符集* @return String* @throws IOException*/private static String doPostByJSON(String url, Map<String, String> headers, JSONObject data, String encoding) throws IOException {// 请求返回结果String resultJson = null;// 创建ClientCloseableHttpClient client = HttpClients.createDefault();// 发送请求,返回响应对象CloseableHttpResponse response = null;// 创建HttpPost对象HttpPost httpPost = new HttpPost();/*** setConnectTimeout:设置连接超时时间,单位毫秒。* setConnectionRequestTimeout:设置从connect Manager(连接池)获取Connection* 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。* setSocketTimeout:请求获取数据的超时时间(即响应时间),单位毫秒。* 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。*/RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();httpPost.setConfig(requestConfig);try {// 设置请求地址httpPost.setURI(new URI(url));// 设置请求头packageHeader(headers, httpPost);// 设置实体httpPost.setEntity(new StringEntity(JSON.toJSONString(data)));// 发送请求,返回响应对象response = client.execute(httpPost);// 获取响应状态int status = response.getStatusLine().getStatusCode();if (status != HttpStatus.SC_OK) {System.out.println("响应失败,状态码:" + status);}// 获取响应结果resultJson = EntityUtils.toString(response.getEntity(), encoding);} catch (Exception e) {e.printStackTrace();} finally {release(response, client);}return resultJson;}/*** POST请求xml参数* @param url* @param requestDataXml* @return String*/public static String doPostByXml(String url, String requestDataXml) {CloseableHttpClient httpClient = null;CloseableHttpResponse response = null;String result = "";try {//创建httpClient实例httpClient = HttpClients.createDefault();//创建httpPost远程连接实例HttpPost httpPost = new HttpPost(url);//配置请求参数实例RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)//设置连接主机服务超时时间.setConnectionRequestTimeout(35000)//设置连接请求超时时间.setSocketTimeout(60000)//设置读取数据连接超时时间.build();//为httpPost实例设置配置httpPost.setConfig(requestConfig);//设置请求参数httpPost.setEntity(new StringEntity(requestDataXml,"UTF-8"));//设置请求头内容httpPost.addHeader("Content-Type","text/xml");//执行post请求得到返回对象response = httpClient.execute(httpPost);//通过返回对象获取数据HttpEntity entity = response.getEntity();//将返回的数据转换为字符串result = EntityUtils.toString(entity);} catch (Exception e) {e.printStackTrace();} finally {//关闭资源if (null != response) {try {response.close();} catch (IOException e) {e.printStackTrace();}}if (null != httpClient) {try {httpClient.close();} catch (IOException e) {e.printStackTrace();}}}return result;}/*** Description: 封装请求头** @param params* @param httpMethod*/public static void packageHeader(Map<String, String> params, HttpRequestBase httpMethod) {// 封装请求头if (params != null) {Set<Map.Entry<String, String>> entrySet = params.entrySet();for (Map.Entry<String, String> entry : entrySet) {// 设置到请求头到HttpRequestBase对象中httpMethod.setHeader(entry.getKey(), entry.getValue());}}}/*** Description: 封装请求参数** @param params* @param httpMethod* @throws UnsupportedEncodingException*/public static void packageParam(Map<String, Object> params, HttpEntityEnclosingRequestBase httpMethod)throws UnsupportedEncodingException {// 封装请求参数if (null != params && params.size() > 0) {List<NameValuePair> nvps = new ArrayList<NameValuePair>();Set<Map.Entry<String, Object>> entrySet = params.entrySet();for (Map.Entry<String, Object> entry : entrySet) {nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));}// 设置到请求的http对象中httpMethod.setEntity(new UrlEncodedFormEntity(nvps, ENCODING));}}/*** @Title: sendGet* @Description: TODO(发送get请求)* @author wangxy* @date 2018年5月14日 下午2:39:01* @param url      请求地址* @param params   请求参数* @param encoding 编码* @return String* @throws IOException*/private static String sendGet(String url, Map<String, Object> params, String encoding) throws IOException {// 请求结果String resultJson = null;// 创建clientCloseableHttpClient client = HttpClients.createDefault();//响应对象CloseableHttpResponse response = null;// 创建HttpGetHttpGet httpGet = new HttpGet();try {// 创建uriURIBuilder builder = new URIBuilder(url);// 封装参数if (params != null) {for (String key : params.keySet()) {builder.addParameter(key, params.get(key).toString());}}URI uri = builder.build();// 设置请求地址httpGet.setURI(uri);//设置配置请求参数RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)//连接主机服务超时时间.setConnectionRequestTimeout(35000)//请求超时时间.setSocketTimeout(60000)//数据读取超时时间.build();// 发送请求,返回响应对象response = client.execute(httpGet);// 获取响应状态int status = response.getStatusLine().getStatusCode();if (status != HttpStatus.SC_OK) {System.out.println("响应失败,状态码:" + status);}// 获取响应数据resultJson = EntityUtils.toString(response.getEntity(), encoding);} catch (Exception e) {e.printStackTrace();} finally {release(response, client);}return resultJson;}/*** Description: 释放资源** @param httpResponse* @param httpClient* @throws IOException*/public static void release(CloseableHttpResponse httpResponse, CloseableHttpClient httpClient) throws IOException {// 释放资源if (httpResponse != null) {httpResponse.close();}if (httpClient != null) {httpClient.close();}}}

然后创建后端的Controller,前端将手机号传递过来

@Reference(interfaceClass = RedisService.class,version = "1.0.0",check = false,timeout = 15000)private RedisService redisService;//这里部署了dubbo以及redis,将验证码存入redis方便验证@RequestMapping("/user/messageCode")@ResponseBodypublic Result sendMessageCode(@RequestParam("phone") String phone) throws Exception {//通过第三方接口发送短信验证码String randomNum = getRandNum(6);System.out.println("本次验证码为:"+randomNum);String url ="https://way.jd.com/kaixintong/kaixintong";Map<String, String> params = new HashMap<>();params.put("appkey","你的appkey");//你的appkeyparams.put("mobile",phone);params.put("content","【凯信通】您的验证码是:"+randomNum);
//        String jsonStr = HttpClientUtils.doGet(url,params);String jsonStr = "{\n" +"    \"code\": \"10000\",\n" +"    \"charge\": false,\n" +"    \"remain\": 0,\n" +"    \"msg\": \"查询成功\",\n" +"    \"result\": \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" ?><returnsms>\\n <returnstatus>Success</returnstatus>\\n <message>ok</message>\\n <remainpoint>-1111611</remainpoint>\\n <taskID>101609164</taskID>\\n <successCounts>1</successCounts></returnsms>\"\n" +"}";  //没有机会的可以使用伪数据尝试JSONObject jsonObject = JSONObject.parseObject(jsonStr);String code = jsonObject.getString("code");if(!StringUtils.equals(code,"10000")){return Result.error("验证码调用错误");}String resultXml = jsonObject.getString("result");Document document = DocumentHelper.parseText(resultXml);Node node = document.selectSingleNode("/returnsms/returnstatus");String returnstatus = node.getText();if (!StringUtils.equals(returnstatus,"Success")){return Result.error("验证码发送失败");}//验证码发送成功了,保存验证码(将验证码保存到redis)redisService.put(phone,randomNum);return Result.success(randomNum);}

这样就结束了
成果如图:

都看到这里了不给我个赞吗?

短信验证码实现(京东万象第三方接口)相关推荐

  1. 短信验证码登录,以及第三方登录

    短信验证码登录 首先去阿里云服务器开通短信服务功能,进入短信服务界面 点击国内消息,申请一个签名和模板 申请一个AccessKey,并且将短信服务的权限加入其中 加入相关的依赖 <depende ...

  2. JAVA实现短信接口的使用、短信验证码的发送(第三方短信平台秒嘀云)

    前言 短信验证登录咱就不多说了,为啥推荐用秒嘀,秒嘀的网页没有广告,并且注册送十块足够新手使用了.但是秒嘀的其它功能需要上传营业执照. 注册账号 https://sms.miaodiyun.com/l ...

  3. JAVA怎么对接第三方短信平台?短信验证码完整API文档

    验证码短信平台的应用场景,一般包括用户注册.登陆账号.忘记密码.登录异常.支付确认等. 一.用户注册 通常我们会在注册时会用到短信验证码,即用户在网站或软件上注册账号时,企业需要通过验证码确认用户身份 ...

  4. 短信验证码接口风险分析

    不论什么场景验证.鉴权功能不能放在前端 1. 手机号合法性验证     a.民用手机号     b.登录.注册.密码找回等关键接口的短信验证码发送,       不能在接口返回时暴露过多信息,如提示: ...

  5. 系统如何自动识别短信验证码

    很多企业在接入短信验证码服务时会关心平台是否支持自动识别验证码功能.就是平台发送短信验证码时,系统可自动识别验证码,用户无需手动输入,点击确认系统自动抓取的验证码即可.那么如何实现自动识别验证码功能. ...

  6. java短信验证码功能发送的验证码如何校验_发送短信验证码和邮箱验证码—Java实现...

    短信验证码 短信验证码都是调用一些接口来进行短信的发送,短信验证码在登录.注册等操作中使用的最广泛,本文这一节演示如何使用Java制作一个简单的短信验证码登录. 我这里演示使用的是聚合数据的短信接口( ...

  7. 使用java实现手机短信验证码

    使用java实现手机短信验证码 一.配置第三方短信接口 二.代码部分 三.效果展示 一.配置第三方短信接口 我们使用阿里云的短信服务(可以免费体验) 阿里云 进入阿里云的官网,查找短信服务,点击短信控 ...

  8. robotframework(12)修改用户密码(从数据库查询短信验证码)

    一.testcase:修改用户密码需要6个参数(短信验证码.设置的新密码.用户已登录的userid及用户唯一标识.接口校验码.被修改的手机号),故先准备这些参数 二.用户登录请求,(获取userid. ...

  9. java 登陆短信验证码_Java实现短信验证码

    原标题:Java实现短信验证码 声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权:凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记. 短信验证码 短信验证码都是调 ...

最新文章

  1. 如何全面认识联邦学习
  2. 成为 Gartner 广域网基础设施报告领导者第二位,Fortinet 做对了什么?
  3. Sencha Touch 动态修改store的url
  4. 极客编程日历桌面版for mac开发笔记[swift]
  5. Android的Menu状态动态设置方法onPrepareOptionsMenu(Menu menu) (转载)
  6. Codeforces Round #713 (Div. 3)
  7. win32/mfc/qt 异常处理与总结
  8. mongoose populate 返回 指定 字段
  9. VUE项目中 获得多个复选框 checkbox 选中的值(jquery)+ 解决 Uncaught TypeError: Cannot read property ‘push‘ of undefine
  10. IDEA Junit测试
  11. HTML中IE版本条件注释整理
  12. 2006年100款最佳安全工具谱
  13. matlab hspice联合仿真,HSPICE TOOLBOX FOR MATLAB
  14. 产品经理——产品方法论
  15. 傲梅分区助手损害大吗_【分区助手技术员v9.00】磁盘分区工具,很好用!
  16. 今晚8:00 | CEI Lab 软硬件协同优化专题,顶会MICRO最佳论文作者来啦
  17. Docker 2375 端口入侵服务器,部分解决方案
  18. RTL设计(6)- 伪随机数生成器
  19. 【科普】机械硬盘选购
  20. 网易明日之后那个服务器人最多,明日之后:网易“公认”全服前4强营地出炉,竟全部来自一个区...

热门文章

  1. 基于MATLAB的算术编码
  2. mybatis-源码
  3. Java安装方法(详细)
  4. 注册【小程序】和注册页面
  5. HTTPSConnectionPool(host=‘files.pythonhosted.org‘, port=443): Read timed out.
  6. matlab 总谐波失真,分析谐波失真 - MATLAB Simulink Example - MathWorks 中国
  7. .Net 操作Word
  8. ostu阈值分割python实现_Otsu阈值OpenCV Python
  9. 为什么要配置数据源ODBC
  10. Prince and Princess HDU - 4685