短信验证注册,一个完整而优雅的JAVA后端实现

1.用户输入手机号获取验证码开始.
		说明一下,如果需要在获取手机号验证码之前进行一个图片滑块校验,参看前一篇博文
1.1前端获取数据封装类
@Data
public class NoteDTO extends InputObject {

    /**
     * 手机号
     */
    private String UserAccount;
    /**
     * 短信验证码
     */
    private String code;
    /**
     * 滑块校验的uuid
     */
    private String uuid;

    /**
     * 滑块校验的横向滑动的参数
     */
    private Integer moveEnd_X;
}
1.2 判断用户是否存在

这里把主要业务放进了controller层,望周知
首先对手机号判断数据库是否存在,也就是是否已经注册

/**
     * @return 
     * @Author 
     * @Description 校验该账户是否存在
     * @Date 9:38 2019/10/15
     * @Param [sportUserAccountVo]
     **/
    @PostMapping("/userExist")
    public OutputObject getVerificationCode(@RequestBody NoteDTO noteDTO) {

        //查询该账户是否存在
        UserInfoPo byUserAccount = userInfoService.findByUserAccount(noteDTO.getUserAccount());
        if (byUserAccount != null) {
            return new OutputObject(StatusCode.PHONE_NUMBER_RIGISTED.getCode(), StatusCode.PHONE_NUMBER_RIGISTED.getMessage(), new ArrayList());
        }
        return new OutputObject(StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMessage(), new ArrayList());
    }

Service层

 /**
     * @Author 
     * @Description 
     * @Date 14:07 2019/10/14
     * @Param [sportUserAccountVo]
     * @return 
     **/
    @Override
    public UserInfoPo findByUserAccount(String userAccount) {
        //查出该用户的所有信息
        UserInfoPo userInfoPos = userInfoMapper.findUserInfoByUserAccount(userAccount);
        return userInfoPos;

    }

dao层 主要是普通的查询操作,在这里我解释一下OutPutObject是控制层的数据响应,也就是状态码,当然也可以是个对象。

    /**
     * @Author 
     * @Description  
     * @Date 19:44 2019/10/14
     * @Param [userAccount]
     * @return 
     **/
    UserInfoPo findUserInfoByUserAccount(@Param("userAccount") String userAccount);

1.3 发送短信验证码和校验验证码

这里的校验验证码单独分开来方便解耦,后面的很多操作都会用到这个校验功能,或者抽取一个工具类也是可以的。这里校验是在发送短信时我们在Redis中存入,验证时通过用户的标识,从Redis中取出来,相对比较安全的方式。

// An highlighted block
/**
     * @return com.deyi.govaffair.pojo.OutputObject
     * @Description 发送短信方法
     * @Param [noteDTO]
     **/
    @RequestMapping(value = "send", method = RequestMethod.POST)
    public OutputObject messageSend(@RequestBody NoteDTO noteDTO, HttpSession session) {

        //查询该账户是否存在
        UserInfoPo byUserAccount = userInfoService.findByUserAccount(noteDTO.getUserAccount());
        if (byUserAccount != null) {
            return new OutputObject(StatusCode.PHONE_NUMBER_RIGISTED.getCode(), StatusCode.PHONE_NUMBER_RIGISTED.getMessage(), new ArrayList());
        }
        //从Session中获取uuid的值对应的裁剪横向距离
        int CJX = (int) session.getAttribute(noteDTO.getUuid());
        //用户拉取裁剪图片的横向距离
        int moveEnd_X = noteDTO.getMoveEnd_X();

        if (moveEnd_X > CJX - 10 && moveEnd_X < CJX + 10) {    //偏差在10之内
            System.out.println("拼接成功");
            //map.put("YZ", "1");
            LOGGER.info("发送短信:{}", noteDTO);
            if (EmptyUtil.isEmpty(noteDTO.getUserAccount())) {
                return new OutputObject(StatusCode.PHONE_NUMBER_IS_NULL.getCode(), StatusCode.PHONE_NUMBER_IS_NULL.getMessage(), new ArrayList());
            }
            String code = RandomUtil.getRandom(4);
            //调用发送短信服务,发送成功之后存储到redis
            /*
             * phoneNumber 手机号
             * verificationCode 验证码
             * expire过期时间(分钟)
             */
            Map<String, String> map1 = new HashMap<>();
            map1.put("phoneNumber", noteDTO.getUserAccount());
            map1.put("verificationCode", code);
            map1.put("expire", "10");
            RongLianSmsSendUtils.sendVerificationCode(map1);
            redisManager.set(RedisPrefix.MESSAGE_CODE.getInfo() + noteDTO.getUserAccount(), code, 600);
            return new OutputObject(StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMessage(), 1);
        }
        return new OutputObject(StatusCode.FAIL.getCode(), StatusCode.FAIL.getMessage(), 0);
    }


    /**
     * 短信验证码验证接口
     * @param noteDTO
     * @return com.deyi.govaffair.pojo.OutputObject
     * @author 张汉飞
     * @date 2019-07-20 15:22:59
     */
    @RequestMapping(value ="verification", method=RequestMethod.POST)
    public OutputObject messageSendVerification(@RequestBody NoteDTO noteDTO){
        if(EmptyUtil.isEmpty(noteDTO.getUserAccount())){
            return new OutputObject(StatusCode.PHONE_NUMBER_IS_NULL.getCode(),StatusCode.PHONE_NUMBER_IS_NULL.getMessage(),new ArrayList());
        }
        if(EmptyUtil.isEmpty(noteDTO.getCode())){
            return new OutputObject(StatusCode.CODE_IS_NULL.getCode(),StatusCode.CODE_IS_NULL.getMessage(),new ArrayList());
        }
        Object redisMessageCode = redisManager.get(RedisPrefix.MESSAGE_CODE.getInfo() + noteDTO.getUserAccount());
        if(EmptyUtil.isNotEmpty(redisMessageCode) && redisMessageCode.equals(noteDTO.getCode())){
            return new OutputObject(StatusCode.SUCCESS.getCode(),StatusCode.SUCCESS.getMessage(),new ArrayList());
        }
        return new OutputObject(StatusCode.CODE_MISS.getCode(),StatusCode.CODE_MISS.getMessage(),new ArrayList());
    }
1.4当然前面的校验必须通过,接下来才是注册。

在这里我们不厌其烦的对验证码、用户账号、用户信息的校验当然是为了规范和安全。

/**
     * @return com.deyi.govaffair.pojo.OutputObject
     * @Description 用户注册接口
     * @Param [userInfoDTO]
     **/
    @PostMapping("register")
    public OutputObject register(@RequestBody UserInfoDTO userInfoDTO) {

        //判断用户名(手机号是否未空)
        if (EmptyUtil.isEmpty(userInfoDTO.getUserAccount())) {
            return new OutputObject(StatusCode.PHONE_NUMBER_IS_NULL.getCode(), StatusCode.PHONE_NUMBER_IS_NULL.getMessage(), new ArrayList());
        }
        //查询该账户是否存在存在
        UserInfoPo byUserAccount = userInfoService.findByUserAccount(userInfoDTO.getUserAccount());
        if (byUserAccount != null) {
            return new OutputObject(StatusCode.PHONE_NUMBER_RIGISTED.getCode(), StatusCode.PHONE_NUMBER_RIGISTED.getMessage(), new ArrayList());
        }

        if (EmptyUtil.isEmpty(userInfoDTO.getCode())) {
            return new OutputObject(StatusCode.CODE_IS_NULL.getCode(), StatusCode.CODE_IS_NULL.getMessage(), new ArrayList());
        }

        Object redisMessageCode = redisManager.get(RedisPrefix.MESSAGE_CODE.getInfo() + userInfoDTO.getUserAccount());

        //校验验证码
        if (EmptyUtil.isNotEmpty(redisMessageCode) && redisMessageCode.equals(userInfoDTO.getCode())) {
            //将验证码存储在redis中的前缀为 message:code: 的key批量删除
            redisManager.del(RedisPrefix.MESSAGE_CODE.getInfo() + userInfoDTO.getUserAccount());
            //执行保存操作
            OutputObject outputObject = userInfoService.saveUserInfo(userInfoDTO);
            return new OutputObject(StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMessage(), new ArrayList());
        }
        return new OutputObject(StatusCode.CODE_MISS.getCode(), StatusCode.CODE_MISS.getMessage(), new ArrayList());
    }

其中的持久层和业务层只是简单的展示,主要是对数据库的查,增相信对大家都是便饭,思路讲清楚,具体的大家应该都能实现。

  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java登录验证的实现可以参考以下步骤: 1. 创建一个获取验证码的接口,该接口负责给手机号发送验证码并设置验证码缓存,设置过期时间。可以使用短信服务提供商的API发送验证码短信,并将验证码存储在缓存中。\[1\] 2. 创建一个登录接口,该接口接收用户提交的手机号和验证码,并读取缓存中的验证码进行匹配验证。如果验证成功,则生成一个token,并将token返回给客户端。客户端在登录成功后的请求中需要携带该token进行业务请求。\[1\] 3. 在后端代码中,可以使用Java的框架(如Spring MVC)来处理登录验证逻辑。在登录接口中,可以通过调用缓存的API来获取和验证验证码。如果验证成功,可以使用JWT(JSON Web Token)来生成token,并将token返回给客户端。\[1\] 4. 在客户端代码中,可以使用JavaScript来处理登录页面的逻辑。可以通过AJAX请求将用户提交的手机号和验证码发送到后端登录接口进行验证。如果验证成功,可以将返回的token保存在客户端,以便在后续的业务请求中携带。\[2\] 5. 关于token的过期时间,可以根据客户端的类型来定义。例如,对于移动端(如app),可以设置较长的过期时间(通常一个星期)。对于web端,可以设置较短的过期时间(以小时为单位)。可以根据请求头信息来判断客户端的类型,并设置相应的过期时间。\[3\] 总结起来,Java登录验证的实现包括发送验证码、验证验证码、生成token和设置过期时间等步骤。可以使用缓存来存储验证码,并使用JWT来生成和验证token。根据客户端的类型来设置不同的过期时间。 #### 引用[.reference_title] - *1* *3* [【209期】图解用户登录验证业务流程(面试应答推荐)](https://blog.csdn.net/afreon/article/details/122138616)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [java 如何实现登陆和注册的验证码功能](https://blog.csdn.net/niceLiuSir/article/details/78473803)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值