基于session实现共享登录

基于session实现登录

1.发送短信验证码

 

@Override
public Result sendCode(String phone, HttpSession session) {
    //1.校验手机号是否合规
    if (RegexUtils.isPhoneInvalid(phone)) {
        //2.不合规直接返回 错误信息
        return Result.fail("手机号错误");
    }
    //3.如果合规生成验证码
    String code = RandomUtil.randomString(4);
    //4.将验证码保存到session中
    session.setAttribute("code",code);
    //5.发送验证码
    log.info("code: {}",code);
    //返回ok
    return Result.ok();
}

ServletContext:上下文对象,在服务器启动时被创建,关闭时被注销,被所有Servlet共享,可在web.xml中进行配置,存放一些初始化数据,拥有最长的生命周期。

HttpSession:会话对象,浏览器请求服务器时被创建,关闭浏览器窗口或页面不刷新过期时被销毁,拥有较长的生命周期

ServletRequest:请求对象,浏览器每次发送请求时被创建,响应结束之后被销毁,用于存放来自页面的参数和浏览器信息,生命周期最短。

2.短信验证、登录、注册功能

 

@Override
public Result login(LoginFormDTO loginForm, HttpSession session) {
    //1.校验手机号的格式
    String phone = loginForm.getPhone();
    if (RegexUtils.isPhoneInvalid(phone)) {
        //2.不一致直接报错
        return Result.fail("手机号错误");
    }
    //3.比较验证码
    Object cacheCode = session.getAttribute("code");
    String code = loginForm.getCode();
    if(session==null || !cacheCode.toString().equals(code)){
        //4.不一致直接报错
        return Result.fail("错误信息");
    }
    //5.根据手机号查询用户
    LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>();
    query.eq(User::getPhone,loginForm.getPhone());
    User user = this.getOne(query);
    if(user==null){
        //6.不存在直接创建新用户保存到数据库中
        user=createUserWithPhone(loginForm.getPhone());
    }
    //7.最终将用户信息保存到session中
    session.setAttribute("user",user);
    return Result.ok();
}
​
private User createUserWithPhone(String phone) {
    User user = new User();
    user.setPhone(phone);
    user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(6));
    this.save(user);
    return user;
​
}

3.登录校验功能

 

创建拦截器

public class LoginInterceptor implements HandlerInterceptor {
    @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");
        if(user==null){
            //3.如果不存在直接拦截  返回401状态
            response.setStatus(401);
            return false;
        }
        //4.存在  保存到ThreadLocal中实现共享
        UserHolder.saveUser((User) user);
        //5.放行
        return true;
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //避免造成内存泄露
        UserHolder.removeUser();
    }
}

注册拦截器

//注册拦截器  及其相关配置
@Configuration
public class MvcConfig implements WebMvcConfigurer {
    //添加拦截器
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(
                "/shop/**",
                "/voucher/**",
                "/shop-type/**",
                "/upload/**",
                "/blog/hot",
                "/user/code",
                "/user/login"
        );
    }
}
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();
    }
}

ThreadLocal叫做线程变量,意思是ThreadLocal中*填充的变量*属于*当前线程*,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值