首页 > 其他分享 >springsecurity使用:登录与校验

springsecurity使用:登录与校验

时间:2024-07-21 18:41:02浏览次数:5  
标签:String 登录 LoginUser 校验 springsecurity token user loginUser new

首先是引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

默认方案:

首次使用这个空项目的时候他会给你一个默认的账号

账号名为user

密码在控制台输出如下图

 这时再进入后端会直接弹到一个/login的地址,输入上述账号密码即可查看路由的具体内容,也可以输出/logout退出登录

 

springsercurity本质是一个过滤器链

 在默认案例中UsernamePasswordAuthenticationFilter中会调用UserDetailService接口的InMemoryUserDetailManager获取用户信息 ,后续我们需要修改成在数据库中查询信息而非内存中

 

 

自拟方案:

登录

  1. 自定义登录接口:调用ProviderManager认证,通过则生成jwt,并把用户数据存入redis,自定义UserDetailService,把从内存查数据改成从数据库查
    1. 自定义service继承UserDetailService
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
              //查询用户信息
              User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUserName, username));
              if(Objects.isNull(user)){
                  throw new RuntimeException("用户名或密码错误");
              }
              String password = user.getPassword();
              //todo 查询权限信息
              //封装返回
              LoginUser loginUser=new LoginUser();
              loginUser.setUser(user);
              return loginUser;
          }
    2. 实现LoginUser类,继承的UserDetails
      public class LoginUser implements UserDetails 
    3. 这里如果进行测试的话,会报错:PasswordEncoder会拿获得的密码和数据库比对,但是要求数据库内的格式为{id}password,根据id去判断加密方式。所以我们写的时候会用BC替换掉这个方法
      @Configuration
      public class SecurityConfig extends WebSecurityConfigurerAdapter {
          @Bean
          public PasswordEncoder passwordEncoder(){
              return new BCryptPasswordEncoder();
          }
      
      }

      注:这里使用了bc加密之后数据库的密码也应在添加时替换成加密后的密码.bc提供了matches()和encode()两种方法

    4. 添加拦截配置,给登录方法放行一下
       @Override
          protected void configure(HttpSecurity http) throws Exception {
              http
                      .csrf().disable()
                      .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
      
                      .authorizeRequests()
                      .antMatchers("/user/login").anonymous()
                      .anyRequest().authenticated();
          }
    5. 登录service
      public ResponseResult login(User user) {
              //进行用户认证
              UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                      new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
              Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
              if (Objects.isNull(authenticate)) {
                  throw new RuntimeException("用户名或密码错误");
              }
              LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
              String id = loginUser.getUser().getId().toString();
              String jwt = JwtUtil.createJWT(id);
              HashMap<String, String> map = new HashMap<>();
              map.put("token", jwt);
              redisCache.setCacheObject("login:"+id,loginUser);
              return new ResponseResult("登录成功", 200, map);
          }
  2. 校验:获取token后解析获取userid,通过redis获取其中用户数据,并将其存入SecurityContextHolder中
    1. 配置过滤器
      @Component
      public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
          @Autowired
          RedisCache redisCache;
          @Override
          protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
              //获取token并解析
              String token = request.getHeader("token");
              if (!StringUtils.hasText(token)) {
                  filterChain.doFilter(request, response);
                  return;
              }
              String userId;
              try {
                  Claims claims = JwtUtil.parseJWT(token);
                  userId = claims.getSubject();
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
              //从redis中获取用户信息再存入securityContextHolder
              String redisKey = "login:" + userId;
              LoginUser loginUser = redisCache.getCacheObject(redisKey);
              if(Objects.isNull(loginUser)){
                   throw new RuntimeException("用户未登录");
              }
              //todo 权限信息还没写
              SecurityContextHolder.getContext().
                      setAuthentication(new UsernamePasswordAuthenticationToken(loginUser,null,null));
              filterChain.doFilter(request, response);
          }
      }
    2. 添加过滤器
      @Override
          protected void configure(HttpSecurity http) throws Exception {
              http
                      .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
          }

       

为什么要存入信息到SecurityContextHolder中:后续步骤都需要从其中取数据,如果是未认证的状态会导致后面不放行

为什么上述两个位置同样用到了UsernamePasswordAuthenticationToken方法但作用不同:Authentication表示当前访问系统的用户,封装了用户相关信息。

在第一个构造函数中,1.5登录service:我们使用了AuthenticationManager.authenticate()这一方法对数据进行逻辑验证,验证失败则返回结果为null

而第二个构造函数中,2.1配置过滤器:这里手动设置安全信息,此时已经通过安全检查了

 

 

标签:String,登录,LoginUser,校验,springsecurity,token,user,loginUser,new
From: https://www.cnblogs.com/kun1790051360/p/18310046

相关文章

  • Spring Boot实现分布式验证码登录方案
     ​ 博客主页:   南来_北往......
  • PHP系列:使用PHP实现用户登录和注册的功能
    使用PHP实现用户登录和注册的功能使用PHP实现用户登录和注册的功能登陆界面login.php登录处理界面logincheck.php注册界面register.php注册处理界面regcheck.php使用PHP实现用户登录和注册的功能登陆界面login.php<formaction="logincheck.php"method="p......
  • bootstrap4登录注册页面
    <!DOCTYPEhtml><html><head><metacharset="utf-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><title>login</title><metaname="description"content......
  • 麒麟 V10 桌面操作系统使用 root 登录
    国产化的趋势已经势不可挡,首先考虑的就是麒麟操作系统,分为桌面版本和服务器版本。桌面版本的Linux命令使用体验跟Ubuntu基本一致。服务器版本的Linux命令使用体验跟CentOS7基本一致。由于越来越多的项目,在开发时就要求在Linux系统下开发,各种开发工具安装都非常方便,比......
  • Spring boot 与 json_schema ,请求和响应 校验
    java中如何使用json_schema对json进行校验在Java中使用JSONSchema对JSON进行校验,你首先需要选择一个合适的库。一个常用的库是json-schema-validator。以下是如何使用它的基本步骤:添加依赖如果你使用Maven,可以在pom.xml中添加以下依赖:<dependency><groupId>com.g......
  • 设置ssh登陆终端的欢迎信息(linux登录配置,/etc/motd有趣的图案【佛祖保佑】)
    设置ssh终端登陆后的欢迎信息是个很实用的技巧,可以给登陆机器的用户发布一些公告信息,或者做一些有趣的字符图案展示。在这里分享我所知道的两种方法:1.系统级别的提示(即系统的所有用户登陆后都能看到)这个很简单,以root用户身份修改/etc/motd这个文件,将想要展示的文字写入此文件,......
  • 第九节 JMeter基础-高级登录【接口关联-鉴权】
    声明:本文所记录的仅本次操作学习到的知识点,其中商城IP错误,请自行更改。 背景:电商的功能:登录、加入购物车、提交订单。问题:谁把什么商品加入了购物车?这时需要把上一个接口的响应数据(登录成功后返回响应数据token值),作为下一个接口的请求数据(加入购物车时token值作为请求数据),这操......
  • 第八节 JMeter基础-高级登录【数据库数据驱动】
    声明:本文所记录的仅本次操作学习到的知识点,其中商城IP错误,请自行更改。背景:获取数据库用户表中的数据进行登录接口测试。思路:引用jar包【测试计划】。设置数据库的连接信息,取变量名db1--数据源【配置元件】。数据取样器引用数据源,填写查询sql,定义用户名密码变量名【取样器】......
  • FastAPI登录实现(JWT)
    JWT(JSON Web Tokens)一、依赖库安装jwtpipinstalljwt==1.2.0python-jose用于生成和检验JWT令牌pipinstallpython-jose==3.2.0passlib用于处理哈希密码的包支持许多安全哈希算法以及配合算法使用的实用程序推荐的算法是 Bcryptpipinstallpasslib[Bcrypt]==1.7......
  • 第四节 JMeter基础-初级登录【固定用户登录】
    声明:本文所记录的仅本次接口测试所用到的知识点。1.认识JMeter(1)测试计划:测试的起点,所有组件的容器。相当于一个测试项目,对测试计划展开一系列的操作。(2)线程组:一定数量的用户。  ①线程数:1。默认为1,表示一个用户。  ②Ramp-UP时间:1。默认是1秒,表示启动线程的时间。在n秒......