项目需求
后台生成随机6位数作为验证码,发送给手机,同时将验证码存入缓存,用户登录时验证输入的验证码是否过期或者是否正确。
一、发送短信
1.了解短信发送
通过发送短信的API,建立一个URL类的对象打开网络连接,通过连接对象得到输入流,就能实现短信发送
1 URL url= new URL(""https://XXXXXX?phoneNumbers=[手机号]&content=[短信内容]"");//使用方法,拼接参数
2 url.openConnection().getInputStream();封装上述方法
1 import com.alibaba.fastjson.JSONObject;
2 import org.apache.commons.lang.StringUtils;
3
4 import java.io.*;
5 import .HttpURLConnection;
6 import .URL;
7 import .URLConnection;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Map.Entry;
12
13 public class SendRequestMethod {
14
15 /**
16 * 向指定 URL 发送POST方法的请求
17 *
18 * @param url 发送请求的 URL
19 * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
20 * @return 所代表远程资源的响应结果
21 */
22 public static String postMethod(String url, String param, Map<String, String> headParam) {
23 Long s0 = System.currentTimeMillis();
24 PrintWriter out = null;
25 BufferedReader in = null;
26 String result = "";
27 try {
28 URL realUrl = new URL(url);
29 // 打开和URL之间的连接
30 HttpURLConnection conn = (HttpURLConnection)realUrl.openConnection();
31 // 设置通用的请求属性
32 conn.setRequestProperty("accept", "*/*");
33 conn.setRequestMethod("POST");
34 conn.setRequestProperty("Accept-Charset", "UTF-8");
35 conn.setRequestProperty("Content-Type", "application/json");
36 conn.setRequestProperty("charset","UTF-8");
37 if (headParam != null) {
38 for (Entry<String, String> entry : headParam.entrySet()) {
39 conn.setRequestProperty(entry.getKey(), entry.getValue());
40 }
41 }
42 // 发送POST请求必须设置如下两行
43 conn.setUseCaches(false);
44 conn.setDoOutput(true);
45 conn.setDoInput(true);
46 conn.setConnectTimeout(1000000);
47 conn.setReadTimeout(1000000);
48
49 // 获取URLConnection对象对应的输出流
50 if(StringUtils.isNotBlank(param)){
51 out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(),"utf-8"));
52 out.write(param);
53 // flush输出流的缓冲
54 out.flush();
55 }
56
57 // 定义BufferedReader输入流来读取URL的响应
58 in = new BufferedReader(
59 new InputStreamReader(conn.getInputStream(), "utf-8"));
60 String line;
61 while ((line = in.readLine()) != null) {
62 result += line;
63 }
64 } catch (Exception e) {
65 System.out.println("发送 POST 请求出现异常!" + e);
66 System.out.println(JSONObject.toJSONString(e));
67 e.printStackTrace();
68 }
69 //使用finally块来关闭输出流、输入流
70 finally {
71 try {
72 if (out != null) {
73 out.close();
74 }
75 if (in != null) {
76 in.close();
77 }
78 } catch (IOException ex) {
79 ex.printStackTrace();
80 }
81 }
82 return result;
83 }发送短信设置发送内容和手机号
1 import com.alibaba.fastjson.JSONObject;
2 import com.wisesoft.core.util.prop.PropertiesUtil;
3 import org.apache.commons.lang.StringUtils;
4
5 import java.util.*;
6
7 public class SendMessage {
8
9 /**
10 * 短信API服务器地址(根据自己的url设置)
11 */
12 private static String pathUrl= "http://xxxxx";
13
14
15 public static JSONObject send(String content,String... phoneNumbers){
16
17 JSONObject param = new JSONObject(2);
18 param.put("content",content);
19 param.put("phoneNumbers", StringUtils.join(phoneNumbers,","));
20
21 Map<String,String> headParam = new HashMap<>();
22 headParam.put("Content-Type","application/json;charset=UTF-8");
23
24 String requestResult = SendRequestMethod .postMethod(pathUrl,param.toJSONString(),headParam);
25 JSONObject result = JSONObject.parseObject(requestResult );
26 return result;
27 }
28 }二、手机号登录
1.发送短信接口
写接口之前,先写个缓存(这里用的是Redis)的工具类(只写了要用的两个方法)
=1 package com.wisesoft.scenic.service.joggle.utils.redis;
2
3 import com.wisesoft.core.util.StringUtil;
4 import com.wisesoft.core.util.prop.FrameworkProps;
5 import com.wisesoft.scenic.interfaceserver.vo.InterfaceServerVO;
6 import redis.clients.jedis.Jedis;
7 import redis.clients.jedis.JedisPool;
8 import redis.clients.jedis.JedisPoolConfig;
9 import redis.clients.jedis.JedisSentinelPool;
10
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15
16 public class RedisUtil {
17
18 private static JedisSentinelPool sentinelPool;
19 private static JedisPool jedisPool;
20
21 static {
22
23 String str_host = getProperty("redis.host", "");
24 String str_port = getProperty("redis.port", "");
25 String password = getProperty("redis.password", "");
26 int database = getProperty("redis.database", 0);
27 int timeout = getProperty("redis.timeout", 5000);
28 String runmodel = getProperty("redis.runmodel", "");
29
30 //连接池配置
31 JedisPoolConfig config = new JedisPoolConfig();
32 config .setMaxTotal(10);
33 config .setMaxIdle(5);
34 config .setMinIdle(5);
35 .....
36
37 if (StringUtil.isNotBlank(runmodel) && "cluster".equalsIgnoreCase(runmodel)) {
38 // mastername是我们配置给哨兵的服务名称
39 String mastername = getProperty("redis.mastername", "");
40 int port = 6379;
41 // 哨兵信息(举例,根据实际情况不同配置)
42 Set<String> sentinels = new HashSet<String>(Arrays.asList(
43 "10.201.7.171:26379",
44 "10.201.7.175:26379",
45 "10.201.7.176:26379"
46 ));
47 sentinelPool = new JedisSentinelPool(mastername, sentinels, config, timeout, password, database);
48
49 } else {
50 int port = Integer.valueOf(str_port);
51 jedisPool = new JedisPool(config, str_host, port, timeout, password);
52 }
53 }
54
55 private RedisClient() {
56 }
57
58 public static String getProperty(String name, String defaultValue) {
59 return FrameworkProps.getProperty(name, defaultValue);
60 }
61
62 /**
63 * 设置缓存(没有过期时间)
64 *
65 */
66 public static String set(String key, String value) {
67 Jedis jedis = getJedis();
68 try {
69 String val = jedis.set(key, value);
70 return val;
71 } finally {
72 jedis.close();
73 }
74 }
75
76 public static String get(String key) {
77 Jedis jedis = getJedis();
78 try {
79 String val = jedis.get(key);
80 return val;
81 } finally {
82 jedis.close();
83 }
84 }
85
86 /**
87 * 设置缓存(有过期时间)
88 *
89 */
90 public static String set(String key, String value, int second) {
91 Jedis jedis = getJedis();
92 try {
93 String val = jedis.set(key, value);
94 jedis.expire(key, second);
95 return val;
96 } finally {
97 jedis.close();
98 }
99 }
100
101 public static Long del(String key) {
102 Jedis jedis = getJedis();
103 try {
104 Long obj = jedis.del(key);
105 return obj;
106 } finally {
107 jedis.close();
108 }
109 }
110
111 /**
112 * 获取客户端连接
113 *
114 */
115 public static Jedis getJedis() {
116 if (sentinelPool != null) {
117 return sentinelPool.getResource();
118 }
119 return jedisPool.getResource();
120 }
121
122 }
发送短信接口代码如下:
1 @RequestMapping(value = "/sendMessage", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
2 @ResponseBody
3 public String sendMessage(@RequestBody String jsonStr) {
4 JSONObject object = JSON.parseObject(jsonStr);
5 String phone = object.getString("phone");
6 JSONObject object = new JSONObject();
7 // 随机生成验证码
8 String verifyCode = (int)(Math.random()* 900000 + 100000)+"";
9
10 // redis配置,实际应该封装一个工具类,这里简单写一下
11 RedisUtil.set(phone + "_verifyCode", verifyCode, 600);
12 String content = "【CSDN】验证码:"+verifyCode+",您正在使用短信验证码登录,有效期10分钟。";
13 JSONObject send = SendMessage.send(content, phone);
14 if(send != null && 200 == send.getIntValue("code")){
15 object.put("code",0);
16 object.put("msg","发送成功");
17 return object.toString();
18 } else {
19 object.put("code",1);
20 object.put("msg","发送失败");
21 return object.toString();
22 }
23
24 }2.登录接口
代码如下:
1 @RequestMapping(value = "/login", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
2 @ResponseBody
3 public String login(@RequestBody String jsonStr) {
4 JSONObject object = JSON.parseObject(jsonStr);
5 String phone = object.getString("phone");
6 String verifyCode = object.getString("verifyCode");
7 JSONObject object = new JSONObject();
8
9 if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(verifyCode)) {
10 object.put("code",1);
11 object.put("msg","手机号或验证码不能为空");
12 return object.toString();
13 } else if (!loginService.checkPhone(phone)) {
14 object.put("code",1);
15 object.put("msg","输入的手机号非法,请输入正确的手机号");
16 return object.toString();
17 }
18 return loginService.loginByPhone(phone, verifyCode);
19 }登录业务逻辑
1 @Override
2 public String loginByPhone(String phone, String verifyCode) {
3 JSONObject object = new JSONObject();
4 // 获取短信验证码
5 String codeStr = RedisUtil.get(phone + "_verifyCode");
6 if (StringUtil.isEmpty(codeStr)) {
7 object.put("code",1);
8 object.put("msg","验证码已失效,请重新发送");
9 return object.toString();
10 }
11 // 判断验证码是否正确
12 if (verifyCode.equals(codeStr)) {
13 // 查询用户信息
14 User user = userService.getByPhone(phone);
15 Date date = new Date();
16 // 用户登录信息
17 UserAccount account = new UserAccount();
18 // 判断账号是否存在
19 if (user == null) {
20 // 用户不存在,则注册账号
21 User userInfo= new User();
22 userInfo.setId(UuidUtil.generateUUID());
23 userInfo.setPhoneNum(phone);
24 userInfo.setCreateTime(date);
25 userInfo.setUpdateTime(date);
26 userInfo.setRegTime(date);
27 userInfo.setLastLoginTime(date);
28 userService.insert(userInfo);
29 BeanUtils.copyProperties(userInfo,account);
30 } else {
31 // 用户存在
32 if (user.getLastLoginTime() != null) {
33 date = user.getLastLoginTime();
34 }
35 BeanUtils.copyProperties(user,account);
36 // 更新登录信息
37 user.setLastLoginTime(new Date());
38 userService.update(user);
39 }
40 // 设置缓存(没有过期时间)
41 String userJson = JSONObject.toJSONString(account);
42 RedisUtil.set("user" + account.getUserId(), userJson);
43 object.put("code",0);
44 object.put("msg","登录成功");
45 object.put("result",account);
46 return object.toString();
47 } else {
48 object.put("code",1);
49 object.put("msg","输入验证码不正确");
50 return object.toString();
51 }
52 }
53
54 @Override
55 public boolean checkPhone(String phone) {
56 // 手机号格式(不验证号码段)
57 Pattern p = Pattern.compile("^^1[0-9]{10}$");
58 Matcher m = p.matcher(phone);
59 return m.matches();
60 }总结
以上就是今天要讲的内容,本文仅仅简单介绍了手机验证码登录的流程,很多细节并没有深入,若有问题,还请大家多多指教。
















