企业级设备用户注册的过程设计及完整代码完成

原创
小哥 3年前 (2022-11-09) 阅读数 47 #大杂烩

在上一篇文章中,我写了如何发送它。email验证码和短信验证码,以及界面刷防。然后,在用户输入验证码并点击注册后,注册逻辑将被触发。

流程描述:点击页面发送验证码将调用权限认证系统,然后权限认证系统将远程调用邮件和短信服务系统。然后,用户输入验证码并单击注册,注册将调用许可系统验证验证码。验证通过后,权限系统将调用成员系统进行注册。

首先是在权限服务中编写相关接口。
1.(许可服务)定义注册vo实体类(jsr303校验):

package com.***.***.auth.vo;

import lombok.Data;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;

/**
 * @author guanghaocheng
 * @version 1.0
 * 翅膀被灰尘和雾气稍稍补充。,蜡烛末端的光线增加了太阳和月亮的辉光。
 * @date 2021/7/3 15:11
 * 用户已注册vo
 */
@Data
public class UserRegistVo {

    @NotEmpty(message = "必须提交用户名")
//    @Length(min = 6,max = 18,message = "用户名必须为6-18位")
    private String userName;

    @NotEmpty(message = "密码不能为空")
    private String password;

    @Pattern(regexp = "^[1][3-9][0-9]{9}$]",message = "电话格式不正确。。")
    private String phone;

    @Pattern(regexp = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$",message = "邮箱格式不正确")
    private String mail;

    @NotEmpty(message = "必须填写验证码")
    private String code;
}

2.(许可服务)写作fegin调用会员服务注册功能的接口

@FeignClient("**-member")
public interface MemberFeignService {

    @PostMapping("/member/member/regist")
    public R regist(@RequestBody UserRegistVo vo);
}

3.(许可服务)检查是否可以注册controller:

1、先判定jsr303检查是否通过,从redis确认手机验证码是否正确,如果验证码一致,则删除验证码(令牌机制),然后调用会员服务进行真正的注册。
2成员服务调用成功后,重定向到登录页面(以防止表单重复提交),否则远程服务返回的错误信息将返回到注册页面。
3,重定向的请求数据。RedirectAttributes参数转发。因为RedirectAttributes可以通过session保存信息并在重定向时携带,因此我们需要稍后解决分布式问题。session问题。
4,重定向时,如果未指定host,直接显示注册服务。ip,所以我们重新定义了writehttp://

注意:此处使用的返回值R,是一个封装的泛型返回类,如果感兴趣,也可以使用R类,此处为文章链接:https://blog.csdn.net/qq\_42969135/article/details/111657050。只需使用您在自己的系统中定义的内容

注:JSR303如何使用验证:JSR303验证结果被封装。BindingResult,再结合BindingResult.getFieldErrors()方法获取错误信息,如果存在错误,则重定向到注册页面

@PostMapping("/regist")
    public String regist(@Valid UserRegistVo userRegistVo, BindingResult bindingResult, RedirectAttributes model){
        //前置校验 采用jsr303方式校验
        if(bindingResult.hasErrors()){
            //检查错误,转到注册页面
            Map errors = new HashMap();
            bindingResult.getFieldErrors().stream().map(fieldError -> {
                String field = fieldError.getField();
                String defaultMessage = fieldError.getDefaultMessage();
                errors.put(field,defaultMessage);
                return errors;
            });
            model.addFlashAttribute("erros",errors);
            return "redirect:http://auth.***.com/register.html";
        }
        //预检通过并开始检查验证码是否正确
        String code = userRegistVo.getCode();
        if(!StringUtils.isEmpty(userRegistVo.getPhone())){//接受手机验证码检查
            String s = redisTemplate.opsForValue().get(AuthServerConstant.MAIL_CODE_CACHE_PREFIX + userRegistVo.getPhone());
            if(StringUtils.isEmpty(s)){//redis中的验证码为空
                Map errors = new HashMap<>();
                errors.put("code","验证码无效");
                model.addFlashAttribute("errors",errors);
                return "redirect:http://auth.***.com/register.html";
            }else{//检查验证码是否一致
                if(code.equals(s.split("_")[0])){
                    //只要验证码成功验证一次,就需要删除验证码。(令牌机制)
                    redisTemplate.delete(AuthServerConstant.MAIL_CODE_CACHE_PREFIX + userRegistVo.getPhone());
                    //验证码已通过--开始调用远程服务以真正注册。
                    R r = memberFeignService.regist(userRegistVo);
                    if(r.getCode() == 0){
                        //成功
                        return "redirect:http://auth.***.com/login.html";
                    }else{
                        Map errors = new HashMap<>();
                        errors.put("msg",r.getData("msg",new TypeReference(){}));
                        return "redirect:http://auth.***.com/register.html";
                    }
                }else{
                    Map errors = new HashMap<>();
                    errors.put("code","验证码错误");
                    model.addFlashAttribute("errors",errors);
                    return "redirect:http://auth.***.com/register.html";
                }
            }
        }else if(!StringUtils.isEmpty(userRegistVo.getMail())){//转到邮箱验证
            String v = redisTemplate.opsForValue().get(AuthServerConstant.MAIL_CODE_CACHE_PREFIX + userRegistVo.getMail());
            if(StringUtils.isEmpty(v)){//缓存中的验证码为空。
                Map errors = new HashMap<>();
                errors.put("code","验证码无效");
                model.addFlashAttribute("errors",errors);
                return "redirect:http://auth.***.com/register.html";
            }else{
                if(code.equals(v.split("_")[0])){
                    //删除验证码(令牌机制)
                    redisTemplate.delete(AuthServerConstant.MAIL_CODE_CACHE_PREFIX + userRegistVo.getMail());
                    //验证码已通过,调用远程服务真正进行注册
                    R r = memberFeignService.regist(userRegistVo);
                    if(r.getCode() == 0){
                        //成功
                        return "redirect:http://auth.***.com/login.html";
                    }else{
                        Map errors = new HashMap<>();
                        errors.put("msg",r.getData("msg",new TypeReference(){}));
                        return "redirect:http://auth.***.com/register.html";
                    }
                }else{//验证码不一致
                    Map errors = new HashMap<>();
                    errors.put("code","验证码错误");
                    model.addFlashAttribute("errors",errors);
                    return "redirect:http://auth.***.com/register.html";
                }
            }
        }else{
            Map errors = new HashMap<>();
            errors.put("code","越过了JSR303验证非法请求");
            model.addFlashAttribute("errors",errors);
            return "redirect:http://auth.***.com/register.html";
        }
//        return "redirect:/login.html";
    }

接下来是与成员服务相关的接口编写,即与注册逻辑相关的内容

3.写入会员服务vo,用于接受上级权限服务远程调用传递的数据。

package com.atguigu.***.member.vo;

import lombok.Data;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;

/**
 * @author guanghaocheng
 * @version 1.0
 * 翅膀被灰尘和雾气稍稍补充。,蜡烛末端的光线增加了太阳和月亮的辉光。
 * @date 2021/7/6 20:01
 */
@Data
public class MemberRegistVo {
    @NotEmpty(message = "必须提交用户名")
//    @Length(min = 6,max = 18,message = "用户名必须为6-18位")
    private String userName;

    @NotEmpty(message = "密码不能为空")
    private String password;

    @Pattern(regexp = "^[1][3-9][0-9]{9}$]",message = "电话格式不正确。。")
    private String phone;

    @Pattern(regexp = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$",message = "邮箱格式不正确")
    private String mail;

}

4.异常机制写入

此项目使用异常机制在注册前检查用户名、手机号码和邮箱是否唯一。不是唯一一个抛出异常的,。controller中try实时异常,转到不同的异常,给出不同的错误返回值。
每个自定义异常都是运行时异常,因此继承。RuntimeException


三种异常的代码如下:

package com.****.**.member.exception;

/**
 * @author guanghaocheng
 * @version 1.0
 * 翅膀被灰尘和雾气稍稍补充。,蜡烛末端的光线增加了太阳和月亮的辉光。
 * @date 2021/7/6 20:53
 */
public class EmailExsitException extends RuntimeException {
    public EmailExsitException() {
        super("邮箱已存在");
    }
}

package com.*.*.member.exception;

/**
 * @author guanghaocheng
 * @version 1.0
 * 翅膀被灰尘和雾气稍稍补充。,蜡烛末端的光线增加了太阳和月亮的辉光。
 * @date 2021/7/6 20:53
 */
public class PhoneExsitException extends RuntimeException {
    //自定义异常应该是运行时异常,即继承。RuntimeException

    public PhoneExsitException() {//使用alt+inster键(idea),生成RuntimeException的构造器
        super("电话号码已存在");
    }
}

package com.*.*.member.exception;

/**
 * @author guanghaocheng
 * @version 1.0
 * 翅膀被灰尘和雾气稍稍补充。,蜡烛末端的光线增加了太阳和月亮的辉光。
 * @date 2021/7/6 20:53
 */
public class UserNameExsitException extends RuntimeException {
    public UserNameExsitException() {
        super("用户名已存在");
    }
}

五、(会员服务)从这里开始写注册码(即上面的controller远程调用的服务中的注册功能)

备注:
1上述(1.2)功能在权限认证系统中。
2过程是:点击页面发送验证码将调用权限认证系统,然后权限认证系统将远程调用邮件和短信服务系统。然后,用户输入验证码并单击注册,注册将调用许可系统验证验证码。验证通过后,权限系统将调用成员系统进行注册。
3,这里是会员服务,也就是权限系统远程调用的系统,以便真正注册。

通过 异常机制 判断当前注册的会员姓名和电话号码邮箱是否已注册,如果已注册,则抛出相应的自定义异常,并在返回时封装相应的错误消息。
如果没有注册,则会封装传递的成员信息,并设置默认的成员级别和创建时间。

注册会员服务controller:

@PostMapping("/regist")
    public R regist(@RequestBody MemberRegistVo vo){
        try{//因为我们使用异常机制来检查用户名、手机号码和电子邮件是否重复,以及throw出来因此,这是必要的。try catch一下
            memberService.regist(vo);
        }catch (PhoneExsitException e){
            return R.error(BizCodeEnume.PHONE_EXIST_EXCEPTION.getCode(),BizCodeEnume.PHONE_EXIST_EXCEPTION.getMsg());
        }catch (EmailExsitException e){
            return R.error(BizCodeEnume.EMAIL_EXIST_EXCEPTION.getCode(),BizCodeEnume.EMAIL_EXIST_EXCEPTION.getMsg());
        }catch (UserNameExsitException e){
            return R.error(BizCodeEnume.USER_EXIST_EXCEPTION.getCode(),BizCodeEnume.USER_EXIST_EXCEPTION.getMsg());
        }catch (Exception e){
//            System.out.println("未知异常:"+ e);
            log.error("未知异常"+e);
        }
        return R.ok();
    }

service如下:

    void regist(MemberRegistVo vo);

    void checkPhoneUnique(String phone) throws PhoneExistException;

    void checkUserNameUnique(String userName) throws UserNameExistException;

impl如下:

@Override
    public void regist(MemberRegistVo vo) {
        MemberDao memberDao = this.baseMapper;
        MemberEntity entity = new MemberEntity();

        //设置默认级别
        MemberLevelEntity levelEntity = memberLevelDao.getDefaultLevel();
        entity.setLevelId(levelEntity.getId());

        //检查用户名、手机号码、电子邮件是否唯一。为了使controller使用异常机制的感知异常。
        if(!StringUtils.isEmpty(vo.getPhone())){
            checkPhoneUnique(vo.getPhone());
        }
        if(!StringUtils.isEmpty(vo.getMail())){
            checkEmailUnique(vo.getMail());
        }
        checkUserNameUnique(vo.getUserName());

        //所有这些都被确定为唯一的,并放入实体类中。
        entity.setMobile(vo.getPhone());
        entity.setEmail(vo.getMail());
        entity.setUsername(vo.getUserName());

        //保存密码,密码加密存储 spring匹配时使用提供的密码自动加密算法。match方法匹配很好。不需要存储在数据库中。signsalt值已加密。
        //这种加密方法非常安全,请看看为什么它是安全的:https://www.cnblogs.com/jpfss/p/11023906.html
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(vo.getPassword());
        entity.setPassword(encode);

        //如果您有其他默认信息设置,请进行设置。

        //保存
        memberDao.insert(entity);

    }

    @Override
    public void checkEmailUnique(String email) throws EmailExsitException{
        MemberDao baseMapper = this.baseMapper;
        Integer email1 = baseMapper.selectCount(new QueryWrapper().eq("email", email));
        if(email1 > 0){
            throw new EmailExsitException();
        }
    }

    @Override
    public void checkPhoneUnique(String phone) throws PhoneExsitException{
        MemberDao baseMapper = this.baseMapper;
        Integer mobile = baseMapper.selectCount(new QueryWrapper().eq("mobile", phone));
        if(mobile > 0){
            throw new PhoneExsitException();
        }
    }

    @Override
    public void checkUserNameUnique(String userName) throws UserNameExsitException{
        MemberDao baseMapper = this.baseMapper;
        Integer username = baseMapper.selectCount(new QueryWrapper().eq("username", userName));
        if(username > 0){
            throw new UserNameExsitException();
        }
    }

至此,你完成了! 企业系统注册功能的完整流程和代码实现。 一切都结束了。
如果您想了解如何在前端倒计时验证码或如何发送电子邮件和短信验证码,请在本栏中查看。这些文章已经写好,并在实战中进行了测试。
加油,年轻人!

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门