SpringBoot如何实现持久化登录状态获取

2022-01-24 0 747
目录

SpringBoot 持久化登录状态获取

1.编写登录的controller文件

写入cookie

//登陆成功后
//...将用户账号信息存入数据库中
//写cookie,(因存入数据库,无需写入session了)
            response.addCookie(new Cookie(\"token\",token));

2.编写首页Controller逻辑

@Controller
public class IndexController {
    @Autowired
    private UserMapper userMapper;
    @GetMapping(\"/\")
    public String index(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        if (cookies != null){
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(\"token\")){
                    String token = cookie.getValue();
                    System.out.println(\"准备进数据库\");
                    User user = userMapper.findByToken(token); //去数据库寻找该token值的用户信息
                    System.out.println(user.toString());
                    if(user != null){ //若找到了这个用户信息
                        //写进session,让页面去展示
                        request.getSession().setAttribute(\"user\",user);
                    }
                    break;
                }
            }
        }
        return \"index\";
    }
}

3.运行测试,成功

SpringBoot 实现登录登出,登录态管理

账户模块中必要的功能登录登出,相信这个大家都经常使用了。简单介绍下在SpringBoot中的实现

先说下实现思路:

用户名密码存储在数据库中,前端发出请求,拦截器先检测用户有无登录,若有登录可直接请求接口。无需登录就可请求的接口需要加@NoLogin自定义注解。若未登录,前端跳转到登录页面,调用登录接口,系统在后台验证用户名密码,验证通过将用户信息存储在redis中和线程上下文中。

1.设计表结构

除了必要的用户名 密码 其他账户信息字段大家可根据自己系统需求添加。

CREATE TABLE `t_account` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT \'主键\',
  `name` varchar(64) NOT NULL DEFAULT \'\' COMMENT \'姓名\',
  `mobile` varchar(32) NOT NULL COMMENT \'手机号\',
  `identity` varchar(32) NOT NULL COMMENT \'身份证号码\',
  `user_name` varchar(32) NOT NULL COMMENT \'账户\',
  `password` varchar(64) NOT NULL DEFAULT \'\' COMMENT \'登录密码\',
  `accept_region` bigint(20) NOT NULL COMMENT \'受理中心(网点)编号\',
  `status` int(11) NOT NULL DEFAULT \'1\' COMMENT \'状态:  0 禁用,1 正常,9 删除\',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT \'创建时间\',
  `create_by` bigint(20) DEFAULT NULL COMMENT \'创建人Id\',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT \'修改时间\',
  `update_by` bigint(20) DEFAULT NULL COMMENT \'修改人Id\',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT=\'C端网点人员账户表\';

2.controller层

接收客户端传参,调用接口与数据库信息匹配,匹配成功返回用户信息。并且存储到redis中,且以当前回话sessionid为key,用户信息为value。

@RestController
@RequestMapping(value = WebConstants.WEB_PREFIX + \"/account\")
@Api(tags = \"Account\", description = \"账户模块\")
@NoAuth
public class AccountController { 
    @Autowired
    private AccountService accountService;
 
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    @PostMapping(value = \"/login\")
    @ApiOperation(\"登录\")
    public ResponseVo<AccountVo>login(@RequestBody LoginForm form, HttpServletRequest request,
                                      HttpServletResponse response)   {
 
        HttpSession session=request.getSession();
        AccountDto accountDto=accountService.login(form.getUserName(),form.getPassword());
        if(null==accountDto){
            throw new BizException(\"用户名或密码错误!\");
        }
        redisTemplate.opsForValue().set(session.getId(), JSON.toJSONString(accountDto));
        AccountVo accountVo= BeanCopy.of(accountDto,new AccountVo()).copy(BeanUtils::copyProperties).get();
        accountVo.setAceptRegion(AcceptRegionEnum.getDescByValue(accountDto.getAceptRegion()));
        return ResponseVo.successResponse(accountVo);
    } 
 
    @Login
    @PostMapping(value = \"/logout\")
    @ApiOperation(\"登出\")
    public ResponseVo logout(HttpServletRequest request,HttpServletResponse response){
        HttpSession session=request.getSession();
        session.invalidate();
        redisTemplate.delete(session.getId());
        return ResponseVo.successResponse();
    } 
}

3.创建请求拦截器

创建一个请求拦截器,用于检测用户登录态。通过session_id检测redis中有没有用户信息。如果存在则将用户信息存储当前线程上下文中(用户线程上下文实质就是基于HashMap的缓存),便于后续使用。这一步也可以放在登录成功后(这样也更严谨)。

@Component
public class LoginInterceptor implements HandlerInterceptor { 
    private Logger logger= LoggerFactory.getLogger(LoginInterceptor.class);
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Class<?> clazz = handlerMethod.getBeanType();
        Method m = handlerMethod.getMethod();
 
        //需登录才可以访问的(预约核验模块)
        if (clazz.isAnnotationPresent(NoLogin.class) || m.isAnnotationPresent(NoLogin.class)) {
            return true; 
        }
        HttpSession session=request.getSession();
            //检测redis中是否含有sessionId
            String val=redisTemplate.opsForValue().get(session.getId());
            if(null!=val){
                logger.info(val);
                AccountDto accountDto= JSON.parseObject(val,AccountDto.class);
                AcceptRegionUserVistor vistor=new AcceptRegionUserVistor();
                BeanUtils.copyProperties(accountDto,vistor);
                AcceptRegionUserThreadContext.putSessionVisitor(vistor);
                return true;
            }else{
                response.setStatus(401);
                throw  new BizException(\"401\",\"common.system.user.not.login\");
            }        
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
    } 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
    }
} 

注册拦截器:(注册后的拦截器才会生效哦)

@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {    
    @Autowired
    private LoginInterceptor loginInterceptor;      
    /**
     * 拦截器配置
     *
     * @param registry 注册类
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {        
        registry.addInterceptor(loginInterceptor).addPathPatterns(WebConstants.WEB_PREFIX + \"/**\"); 
        super.addInterceptors(registry);
    }
}

4.登出

获取到当前会话,清空回话信息,删除redis中对应sessionid的用户信息。代码见上第二段代码logout方法。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 SpringBoot如何实现持久化登录状态获取 http://www.20zxx.cn/297500/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务