如何基于Session实现短信登录功能

目录
  • 一、基于Session实现登录
    • 1.1 业务流程图
  • 二、发送短信验证码
    • 2.1 发送短信请求方式及参数说明
  • 三、登录功能
    • 3.1  短信验证的请求方式及路径
    • 3.2  业务层代码实现用户登录
    • 3.3 拦截器——登录验证功能
  • 三、隐藏用户敏感信息
  • 四、session共享问题
  • 总结

一、基于Session实现登录

1.1 业务流程图

二、发送短信验证码

2.1 发送短信请求方式及参数说明

这个地方为什么需要session?  因为我们需要把验证码保存在session当中

     /**
     * 发送手机验证码
     */
    @PostMapping("code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        // TODO 发送短信验证码并保存验证码
//        return Result.fail("功能未完成");
        return userService.sendCode(phone,session);
    }

2.2 业务层代码模拟发送短信

    @Override
    public Result sendCode(String phone, HttpSession session) {
//      1.校验手机号
        if(RegexUtils.isPhoneInvalid(phone)){
//              说明:RegexUtils使我们封装的一个类   isCodeInvalid是里面的静态方法,在这个静态方法里面又调用了另外一个静态方法得以实现
//      2.如果不符合,返回错误信息
            return Result.fail("手机号格式错误");
        }

//      3.符合,生成验证码    6代表生成的验证码的长度  RandomUtil使用这个工具类生成
        String code =  RandomUtil.randomNumbers(6);
//      4.保存验证码到session       key必须是一个字符串,value是一个对象
        session.setAttribute("code",code);
//      5.发送验证码
//        实现起来比较麻烦 我们使用日志假装发送
        log.debug("发送短信验证码成功,验证码:"+code);
        return Result.ok();
    }
}

三、登录功能

3.1  短信验证的请求方式及路径

    /**
     * 登录功能
     * @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
        // TODO 实现登录功能
        return userService.login(loginForm,session);
    }

3.2  业务层代码实现用户登录

流程图:

代码:

    /**
     * 实现用户登录
     * @param loginForm  登录的参数
     * @param session
     * @return
     */
    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {
//      1.校验手机号
        if(RegexUtils.isPhoneInvalid(loginForm.getPhone())){
//              说明:RegexUtils使我们封装的一个类   isCodeInvalid是里面的静态方法,在这个静态方法里面又调用了另外一个静态方法得以实现
//          1.2.如果不符合,返回错误信息
            return Result.fail("手机号格式错误");
        }
//      2.校验验证码
//           2.1 得到code 这个值是真实的code
        Object cacheCode = session.getAttribute("code");
//           2.2 获取用户输入的code
        String code = loginForm.getCode();
        if(cacheCode ==null || !cacheCode.toString().equals(code)){
//      3.不一致,报错
            return Result.fail("验证码错误");
        }

//      4.一致,根据手机号查询用户   .one()代表查询一个  list()代表着查询多个
        User user =query().eq("phone",loginForm.getPhone()).one();

//      5.判断用户是否存在
        if(user ==null){
//      6.不存在,创建新用户并保存
             user = createUserWithPhone(loginForm.getPhone());
        }

//      7.保存用户信息到session中
        session.setAttribute("user",user);
        return Result.ok();
    }

    private User createUserWithPhone(String phone) {
//      1.创建用户
        User user = new User();
        user.setPhone(phone);
//       USER_NICK_NAME_PREFIX其实就是 "user_",这样写更有逼格
        user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10));
//        保存用户
        save(user);

        return user;
    }

3.3 拦截器——登录验证功能

// HandlerInterceptor 这是一个拦截器
public class LoginInterceptor implements HandlerInterceptor {
//  前置拦截   在进入controller之前我们进行登录校验
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//      1.获取session
        HttpSession session  =request.getSession();
//      2.获取session中的用户
        Object user = session.getAttribute("user");
//      3.判断用户是否存在
        if(user == null){
            // 4.不存在,拦截
            response.setStatus(401);  //返回401状态码
            return false;
        }
//      5.存在,保存用户信息到ThreadLocal  保存在当前线程里面的
        UserHolder.saveUser((User)user);
//      6.放行
        return true;
    }
//  在controller执行之后拦截  这个我们在这里不需要
//    @Override
//    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
//    }

//  渲染之后,返回给用户之前   用户业务执行完毕我们要销毁维护信息,避免泄露
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//      移除用户
        UserHolder.removeUser();
    }
}
public class UserHolder {
    private static final ThreadLocal<User> tl = new ThreadLocal<>();

    public static void saveUser(User user){
        tl.set(user);
    }

    public static User getUser(){
        return tl.get();
    }

    public static void removeUser(){
        tl.remove();
    }
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {

//  拦截器的注册器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .excludePathPatterns(
                        "/user/code",
                        "/user/login",
                        "/shop/**",
                        "/blog/hot",
                        "/shop-type/**",
                        "upload/**",
                        "voucher/**"
                );
    }
}
    @GetMapping("/me")
    public Result me(){
        // TODO 获取当前登录的用户并返回
//        直接取就可以了
       User user=  UserHolder.getUser();

        return Result.ok(user);
    }

三、隐藏用户敏感信息

如下图所示,服务器返回的信息有点多,我们为了保护用户的信息,我们需要隐藏部分的内容

所以一开始我们存入session的信息就不应该是完整的信息,这样才能降低服务器的压力

UserServiceImpl中的login方法

//      7.保存用户信息到session中   \
//         BeanUtil.copyProperties(user, UserDTO.class))  会自动的将user中的属性拷贝到UserDTO当中而且也创建出一个UserDTO对象
        session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));

取的时候我们也应该做出变化

LoginInterceptor类

//      5.存在,保存用户信息到ThreadLocal  保存在当前线程里面的
        UserHolder.saveUser((UserDTO)user);

此时我们再登录查询信息,就还剩下三个字段了

四、session共享问题

多台Tomcat并不共享session存储空间,当请求切换到不同的Tomcat服务导致数据丢失的问题

所以这个方案就被pass了

session的替代方案应该满足:

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

所以我们选择Redis

任何一台Tomcat都能访问到Redis,这样就能实现数据共享

总结

到此这篇关于如何基于Session实现短信登录功能的文章就介绍到这了,更多相关Session短信登录内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Redis的共享session应用实现短信登录

    目录 1. 基于 session 实现短信登录 1.1 短信登录流程图 1.2 实现发送短信验证码 1.3 实现短信验证码登录.注册 1.4 实现登录校验拦截器 2. 集群的 session 共享问题 3. 基于 Redis 实现共享 session 登录 3.1 Redis 实现共享 session 登录流程图 3.2 实现发送短信验证码 3.3 实现短信验证码登录.注册 3.4 实现登录校验拦截器 1. 基于 session 实现短信登录 1.1 短信登录流程图 1.2 实现发送短信验证码

  • 如何基于Session实现短信登录功能

    目录 一.基于Session实现登录 1.1 业务流程图 二.发送短信验证码 2.1 发送短信请求方式及参数说明 三.登录功能 3.1  短信验证的请求方式及路径 3.2  业务层代码实现用户登录 3.3 拦截器——登录验证功能 三.隐藏用户敏感信息 四.session共享问题 总结 一.基于Session实现登录 1.1 业务流程图 二.发送短信验证码 2.1 发送短信请求方式及参数说明 这个地方为什么需要session?  因为我们需要把验证码保存在session当中 /** * 发送手机验

  • Redis实现短信登录的企业实战

    目录 一.导入黑马点评项目 1. 导入SQL 2. 前后端分离 3. 导入后端项目 4. 导入前端项目 二.基于Session实现登录流程 1. 发送短信验证码 2. 短信验证码登录.注册 3. 登录验证功能 三.集群的session共享问题 四.基于Redis实现共享session的登录功能 1. 选择合适的数据结构存入Redis 2. 发送短信验证码 3. 短信验证码登录.注册 4. 解决token刷新问题 一.导入黑马点评项目 黑马点评项目主要包括以下功能: 这一章主要介绍短信登录功能,短

  • 微信小程序实现短信登录的实战

    目录 1.界面效果预览 2.uView安装 3.uView配置 3.1 main.js中引入 3.2 uni.scss中引入 3.3 App.vue中引入 3.4 pages.json中配置 4.短信登录界面 5.点击获取验证码接口 项目要求增加短信登录及人脸识别登录功能,下面我们来实现下短信登录功能 1.界面效果预览 2.uView安装 uView官网:https://www.uviewui.com 以npm安装为例,执行:npm install uview-ui即可 3.uView配置 3.

  • 基于Redis实现短信验证码登录项目示例(附源码)

    目录 Redis短信登录流程描述 短信验证码的发送 短信验证码的验证 是否登录的验证 源码分析 模拟发送短信验证码 短信验证码的验证 校验是否登录 登录验证优化 Redis短信登录流程描述 短信验证码的发送 用户提交手机号,系统验证手机号是否有效,毕竟无效手机号会消耗你的短信验证次数还会导致系统的性能下降.如果手机号为无效的话就让用户重新提交手机号,如果有效就生成验证码并将该验证码作为value保存到redis中对应的key是手机号,之所以这么做的原因是保证key的唯一性,如果使用固定字符串作为

  • Laravel框架实现发送短信验证功能代码

    Laravel框架简介: Laravel是一套简洁.优雅的PHP Web开发框架(PHP Web Framework).它可以让你从面条一样杂乱的代码中解脱出来:它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁.富于表达力. Laravel短信验证思路详解 今天在做到用户注册和个人中心的安全管理时,我实现借助第三方短信平台在Laravel框架中进行手机验证的设置; 由于我做的是一个为客户提供医疗咨询和保健品网站,所以我们对客户个人隐私的保护显得尤为重要,因而在客户登录后进入个人中心前,

  • Spring MVC 中 短信验证码功能的实现方法

    在外部网站中短信的验证很有必要,比如在实现注册.验证用户信息等的情况下.在SpringMVC中的实现如下: 短信接口 短信接口,有些企业会购买的有移动的短信平台接口.如果是个人或者是小企业可以使用一些云服务的.比如百度的API Store上面的. 我使用的是:http://apistore.baidu.com/apiworks/servicedetail/1018.html 当然短信接口肯定都是要付费的,而且是基于模板的,具体的使用说明可以看这个网址里面的使用说明. 前端界面 前端的界面,可能如

  • javaweb项目如何实现手机短信登录

    手机号登录在现在的项目中用的场景非常多,实现起来也不难,今天我们就一起来通过演示实现登录过程.   一.首先需要注册个第三方的账户,比如秒嘀科技等,然后拿到三个参数值:QUERAY_PATH   ACCOUNT_SID       AUTH_TOKEN 二.编写获取验证码类getMessage.java private static final String QUERAY_PATH="xxxx"; private static final String ACCOUNT_SID=&quo

  • Spring Security 自定义短信登录认证的实现

    自定义登录filter 上篇文章我们说到,对于用户的登录,security通过定义一个filter拦截login路径来实现的,所以我们要实现自定义登录,需要自己定义一个filter,继承AbstractAuthenticationProcessingFilter,从request中提取到手机号和验证码,然后提交给AuthenticationManager: public class SmsAuthenticationFilter extends AbstractAuthenticationPro

  • 基于Python制作短信发送程序

    目录 一.Python短信发送界面最后的效果 二.准备:注册腾讯云账号并配置短信功能 三.初始化短信发送程序窗口 3.1初始化窗口菜单 3.2初始化窗口控件 3.3编写事件触发程序 四.完整源代码 一.Python短信发送界面最后的效果 二.准备:注册腾讯云账号并配置短信功能 (1)注册腾讯云账号 登录腾讯云网址 (2)获取AppID.AppKey 在短信功能页面下,从应用管理>应用列表,获取ID.Key. (3)创建签名 在短信功能页面下,进入国内短信>签名管理,创建签名. (4)创建正文模

随机推荐