表结构 user_info

CREATE TABLE user_info (
user_id varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ‘用户id’,
nick_name varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ‘昵称’,
avatar varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘头像’,
email varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ‘邮箱’,
password varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ‘密码’,
sex tinyint(1) DEFAULT NULL COMMENT ‘0:女 1:男 2:未知’,
birthday varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘出生日期’,
school varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘学校’,
person_introduction varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘个人简介’,
join_time datetime NOT NULL COMMENT ‘加入时间’,
last_login_time datetime DEFAULT NULL COMMENT ‘最后登录时间’,
last_login_ip varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘最后登录IP’,
status tinyint(1) NOT NULL DEFAULT ‘1’ COMMENT ‘0:禁用 1:正常’,
notice_info varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘空间公告’,
total_coin_count int NOT NULL COMMENT ‘硬币总数量’,
current_coin_count int NOT NULL COMMENT ‘当前硬币数’,
theme tinyint(1) NOT NULL DEFAULT ‘1’ COMMENT ‘主题’,
PRIMARY KEY (user_id) USING BTREE,
UNIQUE KEY idx_key_email (email) USING BTREE,
UNIQUE KEY idx_nick_name (nick_name) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT=‘用户信息’;
在这里插入图片描述

生成验证码

	@RequestMapping(value = "/checkCode")
    public ResponseVO checkCode() {
    	//生成验证码,指定大小为100*42
        ArithmeticCaptcha captcha = new ArithmeticCaptcha(100, 42);
        //获得该验证码对应的答案
        String code = captcha.text();
        String checkCodeKey = redisComponent.saveCheckCode(code);
        //生成验证码图片对应的base64编码
        String checkCodeBase64 = captcha.toBase64();
        //将该验证码对应的key和答案存入map放回给前端
        Map<String, String> result = new HashMap<>();
        result.put("checkCode", checkCodeBase64);
        result.put("checkCodeKey", checkCodeKey);
        return getSuccessResponseVO(result);
    }
redisComponent.saveCheckCode(code);
 public String saveCheckCode(String code) {
 		//生成唯一的key值,来确定一个对应的验证码
        String checkCodeKey = UUID.randomUUID().toString();
        //将Constants.REDIS_KEY_CHECK_CODE + checkCodeKey作为键
     	//code(验证码的答案)作为值
     	//存入redis中并设置保留时间为10分钟
        redisUtils.setex(Constants.REDIS_KEY_CHECK_CODE + checkCodeKey,
         code, 
         Constants.REDIS_KEY_EXPIRES_ONE_MIN * 10);
         //返回该验证码对应的key值(确定该验证码的key)
        return checkCodeKey;
    }

注册

	@RequestMapping(value = "/register")
    public ResponseVO register(
    		@NotEmpty @Email @Size(max = 150) String email,@NotEmpty @Size(max = 20) String nickName,
   			@NotEmpty @Pattern(regexp =Constants.REGEX_PASSWORD) String registerPassword, 
            @NotEmpty String checkCodeKey, @NotEmpty String checkCode) {
            
        try {
        //从前端传入验证码对应的key值,作为键从redis中获取值(验证码的答案
        //checkCode为前端用户输入的答案
            if (!checkCode.equalsIgnoreCase(redisComponent.getCheckCode(checkCodeKey))) {
                throw new BusinessException("图片验证码不正确");
            }
            userInfoService.register(email, nickName, registerPassword);
            return getSuccessResponseVO(null);
        } finally {
        	//清除在redis中的验证码信息
            redisComponent.cleanCheckCode(checkCodeKey);
        }
        
    }
userInfoService.register(email, nickName, registerPassword);
	@Override
	//事务注解
    @Transactional(rollbackFor = Exception.class)
    public void register(String email, String nickName, String password) {
    
    	//根据email查询用户
    	//如果用户存在就要换一个email
        UserInfo userInfo = this.userInfoMapper.selectByEmail(email);
        if (null != userInfo) {
            throw new BusinessException("邮箱账号已经存在");
        }
        
        //根据nickName查询用户
    	//如果用户存在就要换一个nickName
        UserInfo nickNameUser = this.userInfoMapper.selectByNickName(nickName);
        if (null != nickNameUser) {
            throw new BusinessException("昵称已经存在");
        }
        
        //随机生成用户id
        String userId = StringTools.getRandomNumber(Constants.LENGTH_10);
        //设置用户信息并存入数据库
        userInfo = new UserInfo();
        userInfo.setUserId(userId);
        userInfo.setNickName(nickName);
        userInfo.setEmail(email);
        userInfo.setPassword(StringTools.encodeByMD5(password));
        userInfo.setJoinTime(new Date());
        userInfo.setStatus(UserStatusEnum.ENABLE.getStatus());
        userInfo.setSex(UserSexEnum.SECRECY.getType());
        userInfo.setTheme(Constants.ONE);

		//从redis中获取系统设置(初始硬币数量)
        SysSettingDto sysSettingDto = redisComponent.getSysSettingDto();
        userInfo.setTotalCoinCount(sysSettingDto.getRegisterCoinCount());
        userInfo.setCurrentCoinCount(sysSettingDto.getRegisterCoinCount());

        this.userInfoMapper.insert(userInfo);
    }

登录

	@RequestMapping(value = "/login")
    public ResponseVO login(HttpServletRequest request, HttpServletResponse response, 
    						@NotEmpty @Email String email, @NotEmpty String password,
                            @NotEmpty String checkCodeKey, @NotEmpty String checkCode) {
                            
        try {
            if (!checkCode.equalsIgnoreCase(redisComponent.getCheckCode(checkCodeKey))) {
                throw new BusinessException("图片验证码不正确");
            }
            String ip = getIpAddr();
            TokenUserInfoDto tokenUserInfoDto = userInfoService.login(email, password, ip);
            //令牌保存到客户端的Cookie中。
            //tokenUserInfoDto中的token是从redisComponent.saveTokenInfo(tokenUserInfoDto);
            //方法中存入的
            saveToken2Cookie(response, tokenUserInfoDto.getToken());
            //将用户登录信息放回给前端
            return getSuccessResponseVO(tokenUserInfoDto);
        } finally {
            redisComponent.cleanCheckCode(checkCodeKey);
            //如果Cookie中存在令牌,则清除Redis中的令牌。
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                String token = null;
                for (Cookie cookie : cookies) {
                    if (Constants.TOKEN_WEB.equals(cookie.getName())) {
                        token = cookie.getValue();
                    }
                }
                if (!StringTools.isEmpty(token)) {
                    redisComponent.cleanToken(token);
                }
            }
        }
    }
userInfoService.login(email, password, ip);
	@Override
    public TokenUserInfoDto login(String email, String password, String ip) {
        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("账号已禁用");
        }
        //更新用户的最后登录时间和ip
        UserInfo updateInfo = new UserInfo();
        updateInfo.setLastLoginTime(new Date());
        updateInfo.setLastLoginIp(ip);
        this.userInfoMapper.updateByUserId(updateInfo, userInfo.getUserId());

        TokenUserInfoDto tokenUserInfoDto = CopyTools.copy(userInfo, TokenUserInfoDto.class);
        //将用户登录信息存入redis,并获得token(此时新的token已存入tokenUserInfoDto)
        redisComponent.saveTokenInfo(tokenUserInfoDto);
        //返回用户登录信息
        return tokenUserInfoDto;
    }
TokenUserInfoDto
  private static final long serialVersionUID = -6910208948981307451L;
    private String userId;
    private String nickName;
    private String avatar;
    private Long expireAt;
    private String token;
redisComponent.saveTokenInfo(tokenUserInfoDto);
public void saveTokenInfo(TokenUserInfoDto tokenUserInfoDto) {
		//生成token
        String token = UUID.randomUUID().toString();
        //设置有效期为7天
        tokenUserInfoDto.setExpireAt(System.currentTimeMillis() + Constants.REDIS_KEY_EXPIRES_DAY * 7);
        //将token存入tokenUserInfoDto(传入的为引用对象)
        tokenUserInfoDto.setToken(token);
        //将用户登录信息存入redis,并设置7天的过期时间
        redisUtils.setex(Constants.REDIS_KEY_TOKEN_WEB + token, 
        				tokenUserInfoDto,
         				Constants.REDIS_KEY_EXPIRES_DAY * 7);
    }
saveToken2Cookie(response, tokenUserInfoDto.getToken());
public void saveToken2Cookie(HttpServletResponse response, String token) {
		//创建一个新的Cookie对象,其中Constants.TOKEN_WEB是Cookie的名称,
		//token是Cookie的值。这里假设Constants.TOKEN_WEB是一个在常量类中定义的字符串,用于标识这个Cookie。
        Cookie cookie = new Cookie(Constants.TOKEN_WEB, token);
        //设置7天过期时间
        cookie.setMaxAge(Constants.TIME_SECONDS_DAY * 7);
        //设置Cookie的路径。这里设置为"/",意味着Cookie在整个域名下都是有效的。
        cookie.setPath("/");
        //将创建的Cookie添加到HTTP响应中。这样,当响应发送给客户端时,客户端的浏览器会存储这个Cookie。
        response.addCookie(cookie);
    }

自动登录

在这里插入图片描述

	@RequestMapping(value = "/autoLogin")
    @GlobalInterceptor
    public ResponseVO autoLogin(HttpServletResponse response) {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
        if (tokenUserInfoDto == null) {
            return getSuccessResponseVO(null);
        }
        if (tokenUserInfoDto.getExpireAt() - System.currentTimeMillis() < Constants.REDIS_KEY_EXPIRES_DAY) {
        	//生成新的token并将用户登录信息存入redis
            redisComponent.saveTokenInfo(tokenUserInfoDto);
            //将新的tokne存入cookie
            saveToken2Cookie(response, tokenUserInfoDto.getToken());
        }
        return getSuccessResponseVO(tokenUserInfoDto);
    }
getTokenUserInfoDto()
public TokenUserInfoDto getTokenUserInfoDto() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //从request中获取token
        String token = request.getHeader(Constants.TOKEN_WEB);
        //从redis中利用token得到用户信息并返回
        return redisComponent.getTokenInfo(token);
    }```
Logo

永洪科技,致力于打造全球领先的数据技术厂商,具备从数据应用方案咨询、BI、AIGC智能分析、数字孪生、数据资产、数据治理、数据实施的端到端大数据价值服务能力。

更多推荐