首页 > 其他分享 >SpringSecurity登录时报错栈溢出,StackOverflow,SpringSecurity多端登录实现方案

SpringSecurity登录时报错栈溢出,StackOverflow,SpringSecurity多端登录实现方案

时间:2022-11-23 17:36:12浏览次数:75  
标签:错栈 登录 doctor SpringSecurity user loadUserByUsername import com

最近在用spring security做一套医疗项目,要求一套后端对应两套前端界面,用户(患者)和医生。

先写的用户登录界面,没有问题,再用同样方法写医生登录的时候报错栈溢出 stack overflow。

先看下spring security登录的时序图

1,把前端传过来的用户名和密码封装成UsernamePasswordAuthentication对象

2,调用DaoAuthenticationProvider的authenticate方法进行认证,我们需要写一个类实现springSecurity提供的UserDetailService接口并重写loadUserByUsername方法,

这样在调用authenticate方法时,就会自动调用loadUserByUsername方法,查询数据库与封装的UsernamePasswordAuthentication进行对比,封装用户权限。

debug调试,发现是在执行到这一行,调用loadUserByUsername方法时出现的错误

 分析原因:我在写用户登录的时候,写了一个LoginUserDetail来实现UserDetailsService接口,并重写了loadUserByUsername方法,实现了用户登录。

之后写医生端的登录,以为是一样的套路,写了一个LoginDoctorDetail又一次实现了UserDetailsService接口,并重写了loadUserByUsername方法,在使用医生账号登录时报错stack overflow,网上查询原因,说springSecurity默认只能接受UserDetailService有一个实现类,否则DaoAuthenticProvider就会不知道调用哪个loadUserByUsername方法,会导致框架内部的方法持续递归调用,导致栈溢出 (个人感觉此处框架设计的不太合理,应该提示一下错误原因)

修改方法:既然不能有多个实现类,就干脆都放到一个实现类里,登录方式都是电话+密码,这样就先根据电话查用户表,查到了说明是用户登录,返回springSecurity要求的用户实体类,没查到再继续查医生表,返回医生实体类(医生需要权限控制)

package com.woniu.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.doctor.mapper.DoctorMapper;
import com.woniu.entity.Doctor;
import com.woniu.entity.LoginDoctor;
import com.woniu.entity.LoginUser;
import com.woniu.entity.User;
import com.woniu.user.mapper.UserMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Set;

@Service
public class LoginUserImpl implements UserDetailsService {
    @Resource
    private UserMapper userMapper;

    @Resource
    private DoctorMapper doctorMapper;

    @Override
    public UserDetails loadUserByUsername(String userTel) throws UsernameNotFoundException {
        //因为用户数量肯定远多于医生,所以先查询用户信息
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("tel",userTel);
        //先根据手机号查user
        User user = userMapper.selectOne(queryWrapper);
        if (user != null){
            return new LoginUser(user);
        }
        //没查到user,再查doctor
        QueryWrapper<Doctor> queryWrapper1=new QueryWrapper<>();
        queryWrapper1.eq("tel",userTel);
        Doctor doctor = doctorMapper.selectOne(queryWrapper1);
        if (doctor != null){
            //查询对应的医生信息和权限信息
            Long doctorId = doctor.getId();
            int count = doctorMapper.queryPermission(doctorId);
            Set<String> permissions;
            //count大于零说明医生是组长,获取组长权限
            if (count > 0){
                permissions = doctorMapper.selectLeaderPerms();
            } else{
                permissions = doctorMapper.selectDoctorPerms();
            }
            return new LoginDoctor(doctor,permissions);
        }
        //TODO 如果user和doctor都没查到,再查admin
        return null;
    }
}

 

 总结:此方法实现起来较简单,但是算是投机取巧的一种方法把,在医生登录时需要多查一次用户表,并且需要要求一个手机号不能同时注册用户和医生端两个账号,这样肯定不是最优解,但是由于医生数量肯定远小于用户数量, 应该是可以接受的。

另外在解决问题时还发现了另一种方法可以满足实现多次UserDetailService方法实现多端登录,需要自定义authenticationFileter和authenticatProvider,得对源码有一定理解,虽然实现起来较麻烦,但是比较正规,具体可以参考如下

https://blog.csdn.net/weixin_43738764/article/details/122459141

 

标签:错栈,登录,doctor,SpringSecurity,user,loadUserByUsername,import,com
From: https://www.cnblogs.com/tyleaf/p/16919093.html

相关文章

  • Linux远程服务器免密登录
    1)先需要知道远程服务器id,如172.21.18.1832)打开终端,输入ssh [email protected]进入【远程服务器环境】3)cd~/.ssh进入ssh目录【待添加机器环境】4)ls查看ssh目录存在auth......
  • 第三章. 业务功能开发--登录验证(使用拦截器)
    第三章.业务功能开发--登录验证(使用拦截器)需求登录验证. 用户访问任何业务资源,都需要进行登录验证. *只有登录成功的用户才能访问业务资源 *没有登录成功的用户访......
  • 【Serverless】Unity快速集成认证服务实现邮件登录
    ​概述:认证服务可以为您的应用快速构建安全可靠的用户认证系统,您只需在应用中访问认证服务的相关能力,而不需要关心云侧的设施和实现。本次将带来如何使用Unity编辑器快速......
  • centos修改机器名,设置ssh免密登录
    1、永久修改机器名hostnamectlset-hostnamenode1vi/etc/hosts192.168.2.100node1192.168.2.101node2 2、免密登录①本地客户端生成公私钥:(一路回车默认即可)......
  • 第三章. 业务功能开发--用户登录安全退出
    第三章.业务功能开发--用户登录安全退出1.用户登录需求:用户在登录页面,输入用户名和密码,点击"登录"按钮或者回车,完成用户登录的功能. *用户名和密码不能为空 *用......
  • OH 应用程序集成 AGC 认证服务实现邮箱登录
    前言AppGalleryConnect(简称AGC)是华为整合内部各项优质服务,将其在全球化、质量、安全、工程管理等领域长期积累的能力开放给开发者。通过集成AGC构建服务,可以降低企业开发......
  • 记一次web登录通杀渗透测试
    在渗透测试过程中,碰见的web登录页面特别多,那么我们应该用什么样的思路去进行一个测试呢,下面看看我的一些测试师思路ba测试思路当看见一个这样的web登录框时,会怎么样进行一......
  • 登录方法封装以及404
    普通方式:全局表单验证完成后要做的事情200-token-username-message-push:把这个登录封装成api进行调用api封装:Login页使用api:登录页:el样式调控:404:组件:路......
  • 企业微信登录,前端做跳转
     <template><divclass="register-page-wrapper"><!--<divclass="attach"><divclass="attachTitle">附件</div></div>-->......
  • 【快应用】account.authorize授权码模式登录报错1102
    ​现象描述在快应用中调用 account.authorize 接口获取AuthorizationCode。应用在其服务端发送请求(必须使用POST方式)到华为OAuth2.0授权服务的“https://oauth-login.c......