短信验证码登录功能: 利用redis限制ip,同时保存验证码

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");

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值