当前位置: 首页 > news >正文

彩票网站开发appapp开发网站建设培训班

彩票网站开发app,app开发网站建设培训班,网站建设心得体会,网站建站代码项目实战-黑马点评 项目架构短信登录发送短信验证码 实现思路就是按照上图左一部分&#xff0c; 实现类如下 Slf4j Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {/*** 验证手机号发送验证码** param phone* pa…

项目实战-黑马点评

项目架构

短信登录

发送短信验证码

实现思路就是按照上图左一部分,

实现类如下

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {/*** 验证手机号发送验证码** @param phone* @param session* @return*/@Overridepublic Result sendCode(String phone, HttpSession session) {//1.校验手机号if (RegexUtils.isPhoneInvalid(phone)) {//2.如果不符合,可以返回错误信息return Result.fail("手机号格式错误");}//3.生成验证码String code = RandomUtil.randomNumbers(6);//4.保存验证码到sessionsession.setAttribute("code", code);//5.发送验证码log.debug("发送验证码成功,验证码为:{}",code);//返回okreturn Result.ok();}
}

这里封装了RegexUtils工具类,调用了反向验证手机号方法,我们可以学习一下这个工具类的实现

public class RegexUtils {/*** 是否是无效手机格式* @param phone 要校验的手机号* @return true:符合,false:不符合*/public static boolean isPhoneInvalid(String phone){return mismatch(phone, RegexPatterns.PHONE_REGEX);}/*** 是否是无效邮箱格式* @param email 要校验的邮箱* @return true:符合,false:不符合*/public static boolean isEmailInvalid(String email){return mismatch(email, RegexPatterns.EMAIL_REGEX);}/*** 是否是无效验证码格式* @param code 要校验的验证码* @return true:符合,false:不符合*/public static boolean isCodeInvalid(String code){return mismatch(code, RegexPatterns.VERIFY_CODE_REGEX);}// 校验是否不符合正则格式private static boolean mismatch(String str, String regex){if (StrUtil.isBlank(str)) {return true;}return !str.matches(regex);}
}

其实就是先检查手机号是否为空,如果不为空再把当前手机号字符串按照正则表达式匹配。

短信验证码登录

校验手机号,校验验证码,如果不一致直接返回错误信息。

如果一致,需要查询用户,如果根据当前手机号,用户不存在,那么创建新用户,其实就是insert

这里没有MapperMyBatis-PlusMyBatis的增强工具,内置了大量的方法,无需XML就能完成CRUD

/*** 实现登录功能* @param loginForm* @param session* @return*/
@Override
public Result login(LoginFormDTO loginForm, HttpSession session) {String phone = loginForm.getPhone();//1.校验手机号if(RegexUtils.isPhoneInvalid(phone)){//手机号不符合,返回错误信息return Result.fail("手机号格式错误");}//2.校验验证码Object cacheCode = session.getAttribute("code");String code = loginForm.getCode();if(cacheCode == null || !cacheCode.equals(code)){//3.不一致,报错return Result.fail("验证码错误");}//4.一致,根据手机号查询用户 select * from tb_user where phone = ?User user = query().eq("phone", phone).one();//5.判断用户是否存在if(user == null){//6.不存在,创建新用户并保存user = createUserWithPhone(phone);}//7.保存用户信息到sessionsession.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));return Result.ok();
}private User createUserWithPhone(String phone){
User user = new User();
user.setPhone(phone);
user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
save(user);
return user;
}
登录校验

在访问后端的多个接口的时候,不可能每次访问都得登陆,保证只要登陆一次即可。于是可以使用拦截器统一拦截,获取session信息,如果存在那么放行,并把信息保存到ThreadLocal,保证可以随时调用。如果不存在,那么拦截。

public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取sessionHttpSession session = request.getSession();//2.获取session的用户Object user = session.getAttribute("user");//3.判断用户是否存在if(user == null){//4.不存在,拦截,返回401状态码response.setStatus(401);return false;}//5.存在,保存用户信息到ThreadLocalUserHolder.saveUser((UserDTO) user);//6.放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
}
集群的session共享问题

由于多台Tomcat并不共享session的共享空间,请求切换到不同的Tomcat时就会导致数据丢失。

最开始考虑的是,只要把数据拷贝一份到每个Tomcat即可,但会导致空间浪费问题,因为保存的都是相同数据。

替代方案应满足:

  • 数据共享
  • 内存存储
  • key、value结构

显然可以借助Redis

基于Redis实现共享session登录

发送验证码

改动的地方就是本来储存在session中,现在把验证码保存到Redis中,使用的key是业务+手机号,从而保证唯一性。

@Resource
private StringRedisTemplate stringRedisTemplate;
/*** 验证手机号发送验证码** @param phone* @param session* @return*/
@Override
public Result sendCode(String phone, HttpSession session) {//1.校验手机号if (RegexUtils.isPhoneInvalid(phone)) {//2.如果不符合,可以返回错误信息return Result.fail("手机号格式错误");}//3.生成验证码String code = RandomUtil.randomNumbers(6);//4.保存验证码到session set key value ex 120stringRedisTemplate.opsForValue().set(RedisConstants.LOGIN_CODE_KEY + phone, code,RedisConstants.LOGIN_CODE_TTL, TimeUnit.MINUTES);//5.发送验证码log.debug("发送验证码成功,验证码为:{}",code);//返回okreturn Result.ok();
}
实现登录功能

更新部分在于,取数据从redis中获取,生成的随机token作为令牌和储存用户信息的key。

/*** 实现登录功能* @param loginForm* @param session* @return*/
@Override
public Result login(LoginFormDTO loginForm, HttpSession session) {String phone = loginForm.getPhone();//1.校验手机号if (RegexUtils.isPhoneInvalid(phone)) {//手机号不符合,返回错误信息return Result.fail("手机号格式错误");}//2.校验验证码String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);String code = loginForm.getCode();if (cacheCode == null || !cacheCode.equals(code)) {//3.不一致,报错return Result.fail("验证码错误");}//4.一致,根据手机号查询用户 select * from tb_user where phone = ?User user = query().eq("phone", phone).one();//5.判断用户是否存在if (user == null) {//6.不存在,创建新用户并保存user = createUserWithPhone(phone);}//7.保存用户信息到redis//7.1 随机生成token,作为登录令牌String token = UUID.randomUUID().toString(true);//7.2 将user对象转为HashMap存储UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),CopyOptions.create().ignoreNullValue().setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));//7.3 储存String userKey = LOGIN_USER_KEY + token;stringRedisTemplate.opsForHash().putAll(userKey, userMap);//7.4 设置token有效期stringRedisTemplate.expire(userKey, LOGIN_USER_TTL, TimeUnit.MINUTES);//8.返回tokenreturn Result.ok(token);
}private User createUserWithPhone(String phone) {
User user = new User();
user.setPhone(phone);
user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
save(user);
return user;
}
登录拦截器的优化

我们当前的拦截器存在一个问题,就是拦截了需要登录的请求时,为了避免永久数据对redis的压力,我们在执行登陆后,一般会给token设置有效期,意思是长时间不点击访问页面,那么token就会过期,不再允许访问。但是现在只有一个拦截器,拦截的是需要登录的路径,而且只有在用户登录时会更新token有效期,这样就会导致即使用户在不停操作,但是不需要登录操作的部分功能也不会更新token有效期,同时需要登陆操作的部分也不会更新token有效期。

怎么解决呢?

我们可以定义两个拦截器,一个用来拦截所有路径,但是不做“拦截”处理,主要负责获取token、查询Redis用户、保存到ThreadLocal、更新token有效期、放行。另外一个拦截需要登陆的路径,查询ThreadLocal用户,不存在就拦截,存在则放行。

http://www.dtcms.com/a/591471.html

相关文章:

  • 兰州网站设计公司长沙网站建设费用
  • 网站开发项目的前端后端数据库影院禁止18岁以下观众观影
  • 建设网站简单吗济南城乡建设局官网
  • 检察院门户网站建设情况总结wordpress需要的php版本
  • 网站制作地点sae网站代备案
  • 阜宁县建设局网站文旅品牌建设
  • 如何做自己公司的网站做搜索引擎的网站有哪些
  • 招远网站建设联系电话wordpress默认主题怎么用
  • 找关键词的网站良乡网站建设
  • 温州网站关键词推广昆明建站公司推荐
  • 网站logo是什么意思湖北分行建设银行网站
  • 什么叫网站维护管理咨询公司是做什么的
  • 如何做阿里巴巴的网站首页易推客app拉新平台
  • 游戏网站哪个好制作学校网站的教程
  • 微信订阅号做网站dede网站建设教程云盘
  • python做网站显示表格宣传推广渠道有哪些
  • 石家庄做网站比较好的公司有哪些那种转转假网站怎么做的
  • seo站群系统厦门翔安建设局网站
  • 制作简历哪个网站好食品网站源码
  • 云南旅游网站建设无锡网站制作排名
  • e福州首页绍兴seo排名
  • 网站建设的发展端午节网页设计素材
  • seo建网站灰色广告投放平台
  • 建设一个大型网站需要多少钱包装设计图
  • 模拟网站建设软件百度域名查询官网
  • 重庆专业网站推广报价建设网站课程设计摘要
  • 网站托管维护代运营佛山网站制作平台
  • 网站建设的技术目标织梦wap手机网站模板
  • 有口碑的坪山网站建设服装设计公司logo
  • k网站建设如何制作wordpress模板