最近搞了一個互聯網項目的注冊,需要寫一個手機號驗證(由於之前沒有輪子,只能自己摸索了);
1:基本思路:
1>購買了阿里雲短信服務->下載阿里雲短信發送demo(java版);
2>后端隨機產生二維碼,通過阿里雲短信服務${code}進行發送
3>同時記錄發送的code和客戶端的手機號,存儲在redis中,redis過期時間60秒;
4>用戶注冊提交將客戶端手機號和驗證碼與redis中的key和value對比,存在則注冊成功(同時刪除redis對應緩存數據),不存在則返回;
如需詢問 可加我QQ820688215
========================================================================================================
代碼如下:
redis工具代碼
maven:
<!--阿里雲短信服務-->
<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服務-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
redis 服務類
public class RedisClientServer { private static final Logger logger = LoggerFactory.getLogger(RedisClientServer.class); private static JedisPool jedisPool = null; private static Jedis jedis = null; public static Jedis jedis_object = null; private static String host = "127.0.0.1"; private static String password = "123456"; private static Integer port = 6379; static{ if(jedisPool == null){ JedisPoolConfig config = new JedisPoolConfig(); //設置最大連接數 config.setMaxTotal(500); //設置最大空閑數 config.setMaxIdle(20); //設置最小空閑數 config.setMinIdle(8); //設置超時時間 config.setMaxWaitMillis(3000); //Idle時進行連接掃描 config.setTestWhileIdle(true); //表示idle object evitor兩次掃描之間要sleep的毫秒數 config.setTimeBetweenEvictionRunsMillis(30000); //表示idle object evitor每次掃描的最多的對象數 config.setNumTestsPerEvictionRun(10); //表示一個對象至少停留在idle狀態的最短時間,然后才能被idle object evitor //掃描並驅逐;這一項只有在timeBetweenEvictionRunsMillis大於0時才有意義 config.setMinEvictableIdleTimeMillis(60000); //初始化連接池 jedisPool = new JedisPool(config, host, port); jedis_object = new Jedis( host, port); } } private RedisClientServer() { } private static Jedis getJedisInstance(){ try { if(null == jedis){ jedis = jedisPool.getResource(); jedis.auth(password); } } catch (Exception e) { logger.error("實例化jedis失敗.........", e); } return jedis; } /** * 向緩存中設置字符串內容 *@author liudianpeng.com *@date */ public static boolean set(String key, String value) throws Exception { Jedis jedis = null; try { jedis = getJedisInstance(); jedis.set(key, value); return true; } catch (Exception e) { logger.error("redis set方法失敗...key="+key+" value="+value, e); } finally { jedisPool.close(); } return false; } /** * 向緩存中設置字符串內容 ,設置過期時間 *@author liudianpeng.com *@date */ public static boolean set(String key, String value,Integer seconds) throws Exception { Jedis jedis = null; try { jedis = getJedisInstance(); jedis.set(key, value); jedis.expire(key, seconds); return true; } catch (Exception e) { logger.error("redis set方法失敗...key="+key+" value="+value, e); } finally { jedisPool.close(); } return false; } /** * 根據key 獲取內容 *@author liudianpeng.com *@date */ public static Object get(String key) { Jedis jedis = null; try { jedis = getJedisInstance(); Object value = jedis.get(key); return value; } catch (Exception e) { logger.error("redis get方法失敗...key="+key); } finally { jedisPool.close(); } return null; } /** * 刪除緩存中得對象,根據key *@author liudianpeng.com *@date */ public static boolean del(String key) { Jedis jedis = null; try { jedis = getJedisInstance(); jedis.del(key); return true; } catch (Exception e) { e.printStackTrace(); } finally { jedisPool.close(); } return false; } /** * 根據key 獲取對象 *@author liudianpeng.com *@date */ public static <T> T get(String key, Class<T> clazz) { Jedis jedis = null; try { jedis = getJedisInstance(); String value = jedis.get(key); return JSON.parseObject(value, clazz); } catch (Exception e) { e.printStackTrace(); } finally { jedisPool.close(); } return null; } /** * 設置key過期 *@author *@date */ public static boolean expire(String key,int seconds){ Jedis jedis = null; try { jedis = getJedisInstance(); jedis.expire(key, seconds); return true; } catch (Exception e) { e.printStackTrace(); } finally { jedisPool.close(); } return false; } /** * 判斷是否存在key *@author *@date */ public static Boolean exists(String key){ Jedis jedis = null; try { jedis = getJedisInstance(); return jedis.exists(key); } catch (Exception e) { e.printStackTrace(); return false; }finally { jedisPool.close(); } } }
隨機code生成工具
public class CoreUtils { /** * 生成隨機字符串 * * @param length * @return */ public static String randomString(int length, boolean isNumeric) { String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; if (isNumeric) { base = "0123456789"; } Random random = new Random(); StringBuffer buffer = new StringBuffer(length); for (int i = 0; i < length; i++) { buffer.append(base.charAt(random.nextInt(base.length()))); } return buffer.toString(); } /** * 不重復的參數進行拼裝,返回查詢條件字符串 * * @param parameters 參數map * @param sort 是否按照字典排序 * @return */ public static String generateQueryString(Map<String, Object> parameters, boolean sort) { ArrayList<String> list = new ArrayList<String>(); for (Map.Entry<String, Object> entry : parameters.entrySet()) { // log.debug("參數:{}", entry.getKey()); if (!"".equals(entry.getValue())) { list.add(entry.getKey() + "=" + entry.getValue()); } } String[] arrayToSort = list.toArray(new String[list.size()]); if (sort) { Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); } StringBuffer buffer = new StringBuffer(); for (int i = 0; i < list.size(); i++) { buffer.append(arrayToSort[i]); if (i < (list.size() - 1)) { buffer.append("&"); } } return buffer.toString(); } /** * 根據參數獲得相關簽名 * * @param buffer 加密參數,ASCII 碼從小到大排序(字典序) * @param encrypt 加密方式 SHA1 MD5 * @return */ public static String signature(String buffer, String encrypt, boolean toUpperCase) { String sign = ""; if ("MD5".equals(encrypt)) { // MD5加密 sign = Hashing.md5().hashString(buffer, Charsets.UTF_8).toString(); } else if ("SHA1".equals(encrypt)) { // SHA1加密 sign = Hashing.sha1().hashString(buffer, Charsets.UTF_8).toString(); } if (toUpperCase) { sign = sign.toUpperCase(); } return sign; } /** * 根據參數獲得相關簽名 * * @param params 加密參數,ASCII 碼從小到大排序(字典序) * @param encrypt 加密方式 SHA1 MD5 * @return */ public static String signature(Map params, String encrypt, boolean toUpperCase) { String sign = ""; // 拼接字符串,按照字典排序 String buffer = generateQueryString(params, true); // log.debug("待加密的字符串 => {}", buffer.toString()); if ("MD5".equals(encrypt)) { // MD5加密 sign = Hashing.md5().hashString(buffer, Charsets.UTF_8).toString(); } else if ("SHA1".equals(encrypt)) { // SHA1加密 sign = Hashing.sha1().hashString(buffer, Charsets.UTF_8).toString(); } // log.debug("加密后的字符串 <=> {}", sign); if (toUpperCase) { sign = sign.toUpperCase(); } return sign; } }
阿里雲短信服務配置
/** * SmsDemo 是官方demo * 對其進行了修改, * 1:sendMsg 發送短信消息給客戶端,需要客戶端傳入手機號 */ public class MessageUtils { /** * 發送短信消息方法,返回驗證碼 * @param phone 用戶手機號 * @return true 發送成功 ;false 發送失敗 */ public static Boolean sendMsg(String phone) throws Exception { //設置超時時間-可自行調整 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 = "";//你的accessKeyId,參考本文檔步驟2 final String accessKeySecret = "";//你的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個手機號碼,批量調用相對於單條調用及時性稍有延遲,驗證碼類型的短信推薦使用單條調用的方式 request.setPhoneNumbers(phone); //必填:短信簽名-可在短信控制台中找到 request.setSignName("你的短信簽名"); //必填:短信模板-可在短信控制台中找到 request.setTemplateCode("SMS_0930219321"); String checkCode = CoreUtils.randomString(6, true);//此處是生成6位數驗證碼工具類 //request.setTemplateParam("{\"code\":\"123\"}");//測試用,此處json一定要嚴格按照json格式書寫 request.setTemplateParam("{\"code\":\""+checkCode+"\"}"); //可選-上行短信擴展碼(擴展碼字段控制在7位或以下,無特殊需求用戶請忽略此字段) //request.setSmsUpExtendCode("90997"); //可選:outId為提供給業務方擴展字段,最終在短信回執消息中將此值帶回給調用者 request.setOutId("yourOutId"); //請求失敗這里會拋ClientException異常 SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")){ //請求成功,短信已發送 //將手機號和生成的隨機數存入redis 並設置redis的過期時間 RedisClientServer.set(phone,checkCode,60); } return sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK"); } //測試發送短信 public static void main (String[] args) throws Exception { Boolean s = MessageUtils.sendMsg("13279879821");//手機號 System.out.println("=========="+s); }
//客戶端請求處理
//獲取redis緩存中的手機號(key)和驗證碼(value)://///////////////////////// if ("".equals((RedisClientServer.get(dto.getMobile())).toString())|| null==(RedisClientServer.get(dto.getMobile())).toString()){ return Results.json().render("驗證碼已過期"); }else { //刪除緩存數據 RedisClientServer.del(dto.getMobile()); }