1. 用户通过手机号获取验证码,我们需要根据用户传入的手机号,生成一个随机验证码,然后把验证码通过阿里的短信服务,发送到用户手机上, 同时要对ip进行限制,每隔60秒才能发送验证码,验证码保存在redis里面,用户登录后,清除redis里面的验证码
@Api(value = "用户注册登录",tags = {"用户注册登录controller"})
@RequestMapping("passport")
public interface PassportControllerApi {
@ApiOperation(value = "获得短信验证码",notes = "获得短信验证码",httpMethod = "GET")
@GetMapping("/getSMSCode")
public GraceJSONResult getSMSCode( @RequestParam String mobile, HttpServletRequest request);
}
2. 为什么要传入request参数,因为要通过request获取用户的ip地址,限制ip防止用户重复获取短信,编写下面的工具类:
// 工具类
public class IPUtil {
/**
* 获取请求IP:
* 用户的真实IP不能使用request.getRemoteAddr()
* 这是因为可能会使用一些代理软件,这样ip获取就不准确了
* 此外我们如果使用了多级(LVS/Nginx)反向代理的话,ip需要从X-Forwarded-For中获得第一个非unknown的IP才是用户的有效ip。
* @param request
* @return
*/
public static String getRequestIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
3. 接下来,随机生成6位数的验证码,利用redis保存验证码,设置短信验证码的过期时间,把验证码通过阿里的短信服务发给用户
@RestController
public class PassportController extends BaseController implements PassportControllerApi {
@Override
public GraceJSONResult getSMSCode(String mobile, HttpServletRequest request) {
// 通过上面的工具类获取用户ip2
String userIp = IPUtil.getRequestIp(request);
// 根据用户的ip进行限制,限制用户60秒内只能获取一次验证码
// 以用户ip为key,userip为值,进行保存
redis.setnx60s(MOBILE_SMSCODE + ":" + userIp, userIp);
// 生成随机验证码,并且发送短信 "整数加上字符串转为字符串"
String random = (int) ((Math.random() * 9 + 1) * 100000) + "";
// 阿里云短信服务6
// smsUtils.sendSMS(MyInfo.getMobile(), random);
// 把验证码存入redis,30分钟后过期,用于后续的验证登录,以手机号为key
redis.set(MOBILE_SMSCODE+":"+mobile,random,30*60);
return GraceJSONResult.ok();
}
}
总结要点: 主要是通过redis限制用户不能够在一个ip无限制的要求发送短信
/**
* 如果key不存在,则设置,如果存在,则报错
* @param key
* @param value
*/
public void setnx60s(String key, String value) {
redisTemplate.opsForValue().setIfAbsent(key, value, 60, TimeUnit.SECONDS);
}
// 用户提交一次发送短信验证码后,后端将其ip获取,并存入redis,60秒之内,如果用户重复获取,再以该ip提交,查询redis里面已存在该ip,就会返回false报错
// 可以通过.getAndSet获取原来key键对应的值并重新赋新值
// Object redisKey = redisTemplate.opsForValue().getAndSet("redisKey", "000");