首页 > 其他分享 >【Easy云盘 | 第三篇】登录注册模块上篇(获取验证码、发送邮箱验证码、登录、注册、重置密码)基于AOP实现参数校验

【Easy云盘 | 第三篇】登录注册模块上篇(获取验证码、发送邮箱验证码、登录、注册、重置密码)基于AOP实现参数校验

时间:2024-04-02 09:04:12浏览次数:23  
标签:String 登录 int 验证码 private userInfo 注册 new

在这里插入图片描述

前言

  • 该Easy云盘非原创,原作者为B站程序员老罗
  • 本人不分享本项目源码 ,只记录项目日记,学习项目技术思路,支持项目付费
  • B站项目学习链接:Springboot项目实战 easypan 仿百度网盘 计算机毕业设计 简历项目 项目经验(后端)
  • 该项目难点:上传文件(大文件的分片与合并、视频文件的分片)、删除文件到回收站(文件夹的递归遍历)、恢复回收站的文件(注意文件命名重复问题)、分享文件(生成分享链接、下载文件)

文章目录

4.2登录注册模块设计

4.2.1获取验证码

(1)思路
  • 思路:在登录页面和注册页面均为涉及到一个图片验证码的输入,防止用户拿到该接口去重复刷,避免系统崩溃
(2)接口
  • 获取验证码接口:Get请求

    http://localhost:7090/api/checkCode?type=0
    
  • 提交参数

    • type为0:获取登录注册页面的验证码
    • type为1:获取将要验证邮箱的验证码
    • 区别在于后端在返回session时,设置的key值不同,type为1即将要验证邮箱,当用户输入该验证码后,后端去session中取check_code_key_email为key的值与用户输入的验证码比较,而不是取注册页面的验证码与其比较

    image-20240401200408457

(3)controller层
	@RequestMapping(value = "/checkCode")
    public void checkCode(HttpServletResponse response, HttpSession session, Integer type) throws IOException {
        CreateImageCodeUtils vCode = new CreateImageCodeUtils(130, 38, 5, 10);
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        String code = vCode.getCode();
        if (type == null || type == 0) {
            //该验证码为登录注册页面的验证码
            session.setAttribute(Constants.CHECK_CODE_KEY, code);
        } else {
            //该验证码为验证邮箱的验证码
            session.setAttribute(Constants.CHECK_CODE_KEY_EMAIL, code);
        }
        vCode.write(response.getOutputStream());
    }
(4)CreateImageCodeUtils工具类
  • com.easy.entity.utils.CreateImageCodeUtils类(通用)
public class CreateImageCodeUtils {
    // 图片的宽度。
    private int width = 160;
    // 图片的高度。
    private int height = 40;
    // 验证码字符个数
    private int codeCount = 4;
    // 验证码干扰线数
    private int lineCount = 20;
    // 验证码
    private String code = null;
    // 验证码图片Buffer
    private BufferedImage buffImg = null;
    Random random = new Random();

    public CreateImageCodeUtils() {
        creatImage();
    }

    public CreateImageCodeUtils(int width, int height) {
        this.width = width;
        this.height = height;
        creatImage();
    }

    public CreateImageCodeUtils(int width, int height, int codeCount) {
        this.width = width;
        this.height = height;
        this.codeCount = codeCount;
        creatImage();
    }

    public CreateImageCodeUtils(int width, int height, int codeCount, int lineCount) {
        this.width = width;
        this.height = height;
        this.codeCount = codeCount;
        this.lineCount = lineCount;
        creatImage();
    }

    // 生成图片
    private void creatImage() {
        int fontWidth = width / codeCount;// 字体的宽度
        int fontHeight = height - 5;// 字体的高度
        int codeY = height - 8;

        // 图像buffer
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = buffImg.getGraphics();
        //Graphics2D g = buffImg.createGraphics();
        // 设置背景色
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);
        // 设置字体
        //Font font1 = getFont(fontHeight);
        Font font = new Font("Fixedsys", Font.BOLD, fontHeight);
        g.setFont(font);

        // 设置干扰线
        for (int i = 0; i < lineCount; i++) {
            int xs = random.nextInt(width);
            int ys = random.nextInt(height);
            int xe = xs + random.nextInt(width);
            int ye = ys + random.nextInt(height);
            g.setColor(getRandColor(1, 255));
            g.drawLine(xs, ys, xe, ye);
        }

        // 添加噪点
        float yawpRate = 0.01f;// 噪声率
        int area = (int) (yawpRate * width * height);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            buffImg.setRGB(x, y, random.nextInt(255));
        }

        String str1 = randomStr(codeCount);// 得到随机字符
        this.code = str1;
        for (int i = 0; i < codeCount; i++) {
            String strRand = str1.substring(i, i + 1);
            g.setColor(getRandColor(1, 255));
            // g.drawString(a,x,y);
            // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处

            g.drawString(strRand, i * fontWidth + 3, codeY);
        }
    }

    // 得到随机字符
    private String randomStr(int n) {
        String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
        String str2 = "";
        int len = str1.length() - 1;
        double r;
        for (int i = 0; i < n; i++) {
            r = (Math.random()) * len;
            str2 = str2 + str1.charAt((int) r);
        }
        return str2;
    }

    // 得到随机颜色
    private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色
        if (fc > 255) fc = 255;
        if (bc > 255) bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    /**
     * 产生随机字体
     */
    private Font getFont(int size) {
        Random random = new Random();
        Font font[] = new Font[5];
        font[0] = new Font("Ravie", Font.PLAIN, size);
        font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);
        font[2] = new Font("Fixedsys", Font.PLAIN, size);
        font[3] = new Font("Wide Latin", Font.PLAIN, size);
        font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);
        return font[random.nextInt(5)];
    }

    // 扭曲方法
    private void shear(Graphics g, int w1, int h1, Color color) {
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    }

    private void shearX(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(2);

        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i = 0; i < h1; i++) {
            double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) {
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            }
        }

    }

    private void shearY(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(40) + 10; // 50;

        boolean borderGap = true;
        int frames = 20;
        int phase = 7;
        for (int i = 0; i < w1; i++) {
            double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) {
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            }

        }

    }

    public void write(OutputStream sos) throws IOException {
        ImageIO.write(buffImg, "png", sos);
        sos.close();
    }

    public BufferedImage getBuffImg() {
        return buffImg;
    }

    public String getCode() {
        return code.toLowerCase();
    }
}
(5)测试结果

image-20240329162414791

4.2.2发送邮箱验证码

(1)接口
  • 发送邮箱验证码接口:Post

    http://localhost:7090/api/sendEmailCode
    
  • 编码格式:

    multipart/form-data
    
  • 请求参数:

    image-20240401200947362

(2)controller层
  • 获取session域中名为check_code_key_email的值,比较与用户输入的checkCode值是否相同,不同则输入图片验证码不正确
  • 相同则调用 EmailCodeService的sendEmailCode()方法
    @RequestMapping("/sendEmailCode")
    @GlobalInterceptor(checkLogin = false, checkParams = true)
    public ResponseVO sendEmailCode(HttpSession session,
                                    @VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
                                    @VerifyParam(required = true) String checkCode,
                                    @VerifyParam(required = true) Integer type) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) {
                throw new BusinessException("图片验证码不正确");
            }
            emailCodeService.sendEmailCode(email, type);
            return getSuccessResponseVO(null);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL);
        }
    }
(3)service层
  • EmailCodeServiceImpl的sendEmailCode方法
    • 首先若是注册用户,则校验邮箱是否存在
    • 通过工具类随机生成五位数;再执行发送邮箱的真正逻辑
	@Override
    @Transactional(rollbackFor = Exception.class)
    public void sendEmailCode(String toEmail, Integer type) {
        //如果是注册,校验邮箱是否已存在
        if (type == Constants.ZERO) {
            UserInfo userInfo = userInfoMapper.selectByEmail(toEmail);
            if (null != userInfo) {
                throw new BusinessException("邮箱已经存在");
            }
        }

        String code = StringTools.getRandomNumber(Constants.LENGTH_5);
        sendEmailCode(toEmail, code);

        emailCodeMapper.disableEmailCode(toEmail);
        EmailCode emailCode = new EmailCode();
        emailCode.setCode(code);
        emailCode.setEmail(toEmail);
        emailCode.setStatus(Constants.ZERO);
        emailCode.setCreateTime(new Date());
        emailCodeMapper.insert(emailCode);
    }
  • 发送邮箱的真正逻辑

    1. 导入依赖

      <!--邮件发送-->
      <dependency>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-mail</artifactId>
      	<version>${springboot.version}</version>
      </dependency>
      
    2. 配置邮件发送者信息、密码

      # 配置邮件服务器的地址 smtp.qq.com
      spring.mail.host=smtp.qq.com
      # 配置邮件服务器的端口(465或587)
      spring.mail.port=587
      
      # 配置用户的账号
      spring.mail.username=改成自己的
      # 配置用户的密码
      spring.mail.password=改成自己的(推荐使用qq邮箱的授权登录密码)
      
    3. 使用自动注入的MimeMessageHelper对象、MimeMessage对象来发送邮件

      • 通过AppConfig类加载yml配置好的邮件发送者信息

      • 重要:Redis存放邮件中固定的格式,RedisComponent.getSysSettingsDto()、以及SysSettingDto类:

        	public SysSettingsDto getSysSettingsDto() {
                SysSettingsDto sysSettingsDto = (SysSettingsDto) redisUtils.get(Constants.REDIS_KEY_SYS_SETTING)
                        
                if (sysSettingsDto == null) {
                    sysSettingsDto = new SysSettingsDto();
                    redisUtils.set(Constants.REDIS_KEY_SYS_SETTING, sysSettingsDto);
                }
                return sysSettingsDto;
            }
        
        @JsonIgnoreProperties(ignoreUnknown = true)
        public class SysSettingsDto implements Serializable {
            /**
             * 注册发送邮件标题
             */
            private String registerEmailTitle = "【微网盘】—系统注册邮件";
        
            /**
             * 注册发送邮件内容
             */
            private String registerEmailContent = "您好,非常感谢您注册微网盘账号!您的验证码为 %s ,为了保证您账号的安全性,该验证码有效期为15分钟!";
        
            /**
             * 用户初始化空间大小 5M
             */
            private Integer userInitUseSpace = 5;
        }
        

        发送邮件核心代码

      private void sendEmailCode(String toEmail, String code) {
          try {
              MimeMessage message = javaMailSender.createMimeMessage();
      
              MimeMessageHelper helper = new MimeMessageHelper(message, true);
              //邮件发件人
              helper.setFrom(appConfig.getSendUserName());
              //邮件收件人 1或多个
              helper.setTo(toEmail);
      		
              //获取邮件内容格式
              SysSettingsDto sysSettingsDto = redisComponent.getSysSettingsDto();
      
              //邮件主题
              helper.setSubject(sysSettingsDto.getRegisterEmailTitle());
              //邮件内容
              helper.setText(String.format(sysSettingsDto.getRegisterEmailContent(), code));
              //邮件发送时间
              helper.setSentDate(new Date());
              
              //发送邮件
              javaMailSender.send(message);
      
          } catch (Exception e) {
              logger.error("邮件发送失败", e);
              throw new BusinessException("邮件发送失败");
          }
      }
      

4.2.3基于AOP实现参数校验

(1)添加切面依赖
		<!--切面-->
	    <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectjweaver.version}</version>
        </dependency>
(2)自定义注解—标识哪些类需要被增强
  • com.easypan.annotation.GlobalInterceptor
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface GlobalInterceptor {

    /**
     * 校验登录
     */
    boolean checkLogin() default true;

    /**
     * 校验参数
     */
    boolean checkParams() default false;

    /**
     * 校验管理员
     */
    boolean checkAdmin() default false;
}
(3)定义切面、切点、切点表达式、通知
  • com.easypan.aspect.GlobalOperationAspect
@Component("operationAspect")
@Aspect
public class GlobalOperationAspect {

    private static Logger logger = LoggerFactory.getLogger(GlobalOperationAspect.class);
    private static final String TYPE_STRING = "java.lang.String";
    private static final String TYPE_INTEGER = "java.lang.Integer";
    private static final String TYPE_LONG = "java.lang.Long";

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private AppConfig appConfig;

    /**
     * @Description: 1、requestInterceptor()方法为切点
     *                2、@annotation(com.easypan.annotation.GlobalInterceptor) 为切点表达式
     *                3、只有在执行带有 @GlobalInterceptor注解的方法时,才会触发 requestInterceptor()方法中的逻辑
     */
    @Pointcut("@annotation(com.easypan.annotation.GlobalInterceptor)")
    private void requestInterceptor() {
    }

    //通知
    @Before("requestInterceptor()")
    public void interceptorDo(JoinPoint point) throws BusinessException {
        try {
            Object target = point.getTarget();      //返回被代理的目标对象,即拦截器拦截的目标方法所属的对象实例
            Object[] arguments = point.getArgs();   //方法返回被拦截方法的参数数组

            String methodName = point.getSignature().getName();                             //获取被拦截方法的 Method 对象的名称
            Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();   //返回方法的参数类型数组

            Method method = target.getClass().getMethod(methodName, parameterTypes);        //通过method名称和参数数组获取 方法对象
            GlobalInterceptor interceptor = method.getAnnotation(GlobalInterceptor.class);  //获取该方法上的GlobalInterceptor注解
            if (null == interceptor) {
                return;
            }
            /**
             * 检查是否需要 校验登录
             * 当GlobalInterceptor注解的checkLogin的属性为True 或 checkAdmin属性为true,即需要检验登录
             */
            if (interceptor.checkLogin() || interceptor.checkAdmin()) {
                checkLogin(interceptor.checkAdmin());
            }
            /**
             * 检查是否需要 校验请求路径参数
             * 当GlobalInterceptor注解的checkParams的属性为True,即需要检验请求路径参数
             */
            if (interceptor.checkParams()) {
                validateParams(method, arguments);
            }

        } catch (BusinessException e) {
            logger.error("全局拦截器异常", e);
            throw e;
        } catch (Exception e) {
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        } catch (Throwable e) {
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        }
    }
}
  • 校验登录: checkLogin(Boolean checkAdmin)
	//校验登录
    private void checkLogin(Boolean checkAdmin) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpSession session = request.getSession();
        SessionWebUserDto sessionUser = (SessionWebUserDto) session.getAttribute(Constants.SESSION_KEY);

        //果当前处于开发模式下,并且没有用户登录信息,则尝试自动登录第一个查询到的用户信息
        if (sessionUser == null && appConfig.getDev() != null && appConfig.getDev()) {
            List<UserInfo> userInfoList = userInfoService.findListByParam(new UserInfoQuery());
            if (!userInfoList.isEmpty()) {
                UserInfo userInfo = userInfoList.get(0);
                sessionUser = new SessionWebUserDto();
                sessionUser.setUserId(userInfo.getUserId());
                sessionUser.setNickName(userInfo.getNickName());
                sessionUser.setAdmin(true);
                session.setAttribute(Constants.SESSION_KEY, sessionUser);
            }
        }
        
        //查到的sessionUser仍为空
        if (null == sessionUser) {
            throw new BusinessException(ResponseCodeEnum.CODE_901); //登录超时
        }

        if (checkAdmin && !sessionUser.getAdmin()) {
            throw new BusinessException(ResponseCodeEnum.CODE_404);//普通用户访问管理员页面,请求地址不存在
        }
    }
  • 校验请求参数validateParams

  • 注意:补充@VerifyParam注解:com.easypan.annotation.VerifyParam

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.PARAMETER, ElementType.FIELD})
    public @interface VerifyParam {
        /**
         * 校验正则
         *
         * @return
         */
        VerifyRegexEnum regex() default VerifyRegexEnum.NO;
    
        /**
         * 最小长度
         *
         * @return
         */
        int min() default -1;
    
        /**
         * 最大长度
         *
         * @return
         */
        int max() default -1;
    
        boolean required() default false;
    }
    
 	/**
     * @Description: 校验方法的参数
     * @Parm: Method m:增强方法对象;Object[] arguments:增强方法的参数数组
     */
    private void validateParams(Method m, Object[] arguments) throws BusinessException {
        Parameter[] parameters = m.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Object value = arguments[i];
            VerifyParam verifyParam = parameter.getAnnotation(VerifyParam.class);   //获取每个参前面的@VerifyParam注解
            if (verifyParam == null) {
                //没有加@VerifyParam注解
                continue;
            }
            //基本数据类型
            if (TYPE_STRING.equals(parameter.getParameterizedType().getTypeName()) || TYPE_LONG.equals(parameter.getParameterizedType().getTypeName()) || TYPE_INTEGER.equals(parameter.getParameterizedType().getTypeName())) {
                checkValue(value, verifyParam);
            } else {
                //如果传递的是对象
                checkObjValue(parameter, value);
            }
        }
    }
  • 校验基本数据类型
	/**
     * 校验参数
     */
    private void checkValue(Object value, VerifyParam verifyParam) throws BusinessException {
        Boolean isEmpty = value == null || StringUtils.isEmpty(value.toString());
        Integer length = value == null ? 0 : value.toString().length();

        /**
         * 校验空
         */
        if (isEmpty && verifyParam.required()) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }

        /**
         * 校验长度
         */
        if (!isEmpty && (verifyParam.max() != -1 && verifyParam.max() < length || verifyParam.min() != -1 && verifyParam.min() > length)) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        /**
         * 校验正则
         */
        if (!isEmpty && !StringUtils.isEmpty(verifyParam.regex().getRegex()) && !VerifyUtils.verify(verifyParam.regex(), String.valueOf(value))) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
    }
  • 校验对象
	private void checkObjValue(Parameter parameter, Object value) {
        try {
            String typeName = parameter.getParameterizedType().getTypeName();
            Class classz = Class.forName(typeName);
            Field[] fields = classz.getDeclaredFields();
            for (Field field : fields) {
                VerifyParam fieldVerifyParam = field.getAnnotation(VerifyParam.class);
                if (fieldVerifyParam == null) {
                    continue;
                }
                field.setAccessible(true);
                Object resultValue = field.get(value);
                checkValue(resultValue, fieldVerifyParam);
            }
        } catch (BusinessException e) {
            logger.error("校验参数失败", e);
            throw e;
        } catch (Exception e) {
            logger.error("校验参数失败", e);
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
    }

4.2.4登录

(1)登录接口
  • 登录接口:Post请求

    http://localhost:7090/api/login
    
  • 编码格式:

    multipart/form-data
    
  • 提交参数:

    image-20240401195937412

(2)controller层
	/**
     * @Description: 登录
     */
    @RequestMapping("/login")
    @GlobalInterceptor(checkLogin = false, checkParams = true)
    public ResponseVO login(HttpSession session, HttpServletRequest request,
                            @VerifyParam(required = true) String email,
                            @VerifyParam(required = true) String password,
                            @VerifyParam(required = true) String checkCode) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("图片验证码不正确");
            }
            SessionWebUserDto sessionWebUserDto = userInfoService.login(email, password);
            session.setAttribute(Constants.SESSION_KEY, sessionWebUserDto);
            return getSuccessResponseVO(sessionWebUserDto);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }
(3)service层
	@Override
    public SessionWebUserDto login(String email, String password) {
        UserInfo userInfo = this.userInfoMapper.selectByEmail(email);
        if (null == userInfo || !userInfo.getPassword().equals(password)) {
            throw new BusinessException("账号或者密码错误");
        }
        if (UserStatusEnum.DISABLE.getStatus().equals(userInfo.getStatus())) {
            throw new BusinessException("账号已禁用");
        }
        UserInfo updateInfo = new UserInfo();
        updateInfo.setLastLoginTime(new Date());
        this.userInfoMapper.updateByUserId(updateInfo, userInfo.getUserId());
        SessionWebUserDto sessionWebUserDto = new SessionWebUserDto();
        sessionWebUserDto.setNickName(userInfo.getNickName());
        sessionWebUserDto.setUserId(userInfo.getUserId());
        if (ArrayUtils.contains(appConfig.getAdminEmails().split(","), email)) {
            sessionWebUserDto.setAdmin(true);
        } else {
            sessionWebUserDto.setAdmin(false);
        }
        //用户空间
        UserSpaceDto userSpaceDto = new UserSpaceDto();
        userSpaceDto.setUseSpace(fileInfoService.getUserUseSpace(userInfo.getUserId()));
        userSpaceDto.setTotalSpace(userInfo.getTotalSpace());
        redisComponent.saveUserSpaceUse(userInfo.getUserId(), userSpaceDto);
        return sessionWebUserDto;
    }

4.2.5注册

(1)接口
  • 注册接口:Post

    http://localhost:7090/api/register
    
  • 编码格式:

    multipart/form-data
    
  • 请求参数:

    image-20240401201421458

(2)controller层
	@RequestMapping("/register")
    @GlobalInterceptor(checkLogin = false, checkParams = true)
    public ResponseVO register(HttpSession session,
                               @VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
                               @VerifyParam(required = true, max = 20) String nickName,
                               @VerifyParam(required = true, regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18) String password,
                               @VerifyParam(required = true) String checkCode,
                               @VerifyParam(required = true) String emailCode) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("图片验证码不正确");
            }
            userInfoService.register(email, nickName, password, emailCode);
            return getSuccessResponseVO(null);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }
(3)service层
  • 检验邮箱是否已经存在
  • 检验昵称是否已经存在
  • 校验邮箱验证码 :
	@Override
    @Transactional(rollbackFor = Exception.class)
    public void register(String email, String nickName, String password, String emailCode) {
        UserInfo userInfo = this.userInfoMapper.selectByEmail(email);
        if (null != userInfo) {
            throw new BusinessException("邮箱账号已经存在");
        }
        UserInfo nickNameUser = this.userInfoMapper.selectByNickName(nickName);
        if (null != nickNameUser) {
            throw new BusinessException("昵称已经存在");
        }
        //校验邮箱验证码
        emailCodeService.checkCode(email, emailCode);
        String userId = StringUtils.getRandomNumber(Constants.LENGTH_10);
        userInfo = new UserInfo();
        userInfo.setUserId(userId);
        userInfo.setNickName(nickName);
        userInfo.setEmail(email);
        userInfo.setPassword(StringUtils.encodeByMD5(password));
        userInfo.setJoinTime(new Date());
        userInfo.setStatus(UserStatusEnum.ENABLE.getStatus());
        SysSettingsDto sysSettingsDto = redisComponent.getSysSettingsDto();
        userInfo.setTotalSpace(sysSettingsDto.getUserInitUseSpace() * Constants.MB);
        userInfo.setUseSpace(0L);
        this.userInfoMapper.insert(userInfo);
    }
	@Override
    public void checkCode(String email, String code) {
        EmailCode emailCode = emailCodeMapper.selectByEmailAndCode(email, code);
        if (null == emailCode) {
            throw new BusinessException("邮箱验证码不正确");
        }
        if (emailCode.getStatus() == 1 || System.currentTimeMillis() - emailCode.getCreateTime().getTime() > Constants.LENGTH_15 * 1000 * 60) {
            throw new BusinessException("邮箱验证码已失效");
        }
        emailCodeMapper.disableEmailCode(email);
    }

4.2.6重置密码

(1)接口
  • 重置密码接口:

    http://localhost:7090/api/resetPwd
    
  • 编码格式:

    multipart/form-data
    
  • 请求参数:

    image-20240401202056500

(2)controller层
	@RequestMapping("/resetPwd")
    @GlobalInterceptor(checkLogin = false, checkParams = true)
    public ResponseVO resetPwd(HttpSession session,
                               @VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
                               @VerifyParam(required = true, regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18) String password,
                               @VerifyParam(required = true) String checkCode,
                               @VerifyParam(required = true) String emailCode) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("图片验证码不正确");
            }
            userInfoService.resetPwd(email, password, emailCode);
            return getSuccessResponseVO(null);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }
(3)service层
	@Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPwd(String email, String password, String emailCode) {
        UserInfo userInfo = this.userInfoMapper.selectByEmail(email);
        if (null == userInfo) {
            throw new BusinessException("邮箱账号不存在");
        }
        //校验邮箱验证码
        emailCodeService.checkCode(email, emailCode);

        UserInfo updateInfo = new UserInfo();
        updateInfo.setPassword(StringUtils.encodeByMD5(password));
        this.userInfoMapper.updateByEmail(updateInfo, email);
    }

在这里插入图片描述

标签:String,登录,int,验证码,private,userInfo,注册,new
From: https://blog.csdn.net/weixin_61440595/article/details/137255468

相关文章

  • 圣文深特公司注册
    圣文深特是众多岛国之一,相对来说知名度也更高,主要得益于在这注册公司通常不需要太多的zhi本,而且注册和年度维护成本相对较低,另外圣文深特拥有发达的国际jin融服务部门,包括li岸银行和金rong机构。这些机构为国际客户提供多样化的金rong服务,吸引了加mi货币,和外hui业务的客户前来......
  • Nacos注册中心
    1.Nacos介绍Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件,相对于Eureka功能更加丰富,在国内受欢迎程度高。Nacos安装地址Release1.4.7(Jan15th,2024)·alibaba/nacos·GitHub2.Nacos安装过程下载安装包之后,解压到没有中文的路径下,我这里安装在D盘Nacos默认......
  • Linux——ssh登录很慢解决方法
    1、背景在同一机房中,有多台安装了CentOS7操作系统的服务器,它们的配置除了IP地址不同外基本相同。这些服务器的资源利用率都不高,但在使用SSH连接时,发现有几台服务器连接速度较慢,可能需要等待30-60秒才能提示输入密码,但一旦连接成功后,速度就恢复正常。2、SSH登陆慢原因这种......
  • 京西商城——用户注册和获取用户信息接口开发
    user/views.pyfromdjango.httpimportHttpResponsefromrest_framework.viewsimportAPIViewfromapps.user.modelsimportUserfromapps.user.serializersimportUserSerializerfromutils.ResponseMessageimportUserResponseclassUserView(APIView):......
  • 【验证码逆向专栏】xx80 邮箱多种类验证码逆向分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作......
  • 苹果开发者账号注册及证书生成方法详解
    转载:注册苹果开发者账号的方法在2020年以前,注册苹果开发者账号后,就可以生成证书。但2020年后,因为注册苹果开发者账号需要使用AppleDeveloperapp注册开发者账号,所以需要缴费才能创建ios证书了。所以新政策出来后,注册苹果开发者账号,并缴费成为苹果开发者,才能手工创建证书......
  • 头条项目自媒体端无法登录报404NotFound
    发生缘由搭建头条项目自媒体端运行环境电脑系统版本:Windows1064bitIdea:2023.2(UltimateEdition)Maven:apache-maven-3.6.0Docker:Dockerversion26.0.0,build2ae903eMinIO:加载本地镜像,不清楚版本号jdk版本:jdk-8spring.boot.version:2.3.9.RELEASEminio依赖:7.1.0......
  • 2024年第1期认证人员注册全国统一考试成绩查询今日午时可查
    中国认证认可协会关于2024年第1期认证人员注册全国统一考试成绩查询的通知 各相关机构及人员: 中国认证认可协会(CCAA)于2024年3月2日—3日举办了2024年第1期认证人员注册全国统一考试。4月1日12时起,考生可使用个人证件信息在“认职圈”小程序查询考试成绩(二维码附后),或登录CC......
  • 2024年第1期认证人员注册全国统一考试成绩复查说明
    成绩复查说明考生认为考试成绩有明显异常的,可以在2024年4月3日10时至4月8日24时期间登录CCAA综合服务平台首页,点击个人服务中的在线申请模块-成绩复核申请业务,提出复查分数申请,逾期不予受理。每个考生可在复查期内提交一次申请,不可重复提交。成绩复查仅限于含主观题的《认证......
  • 使用sddm出现无法登录的原因及解决方法
    配置文件介绍SDDM的默认配置文件为/usr/lib/sddm/sddm.conf.d/default.conf配置加载配置目录中的所有文件,然后按下面列出的顺序加载配置文件,后者具有最高优先级。应该对本地配置进行更改。/usr/lib/sddm/sddm.conf.d系统配置目录/etc/sddm.conf.d本地配置目录/e......