Spring Boot实现登录注册的三种基本方式
作者:mmseoamin日期:2024-04-30

JAVA实现登录的方式

  • cookie方式实现
  • session的方式
  • jwt方式实现
    • 1. 添加依赖
    • 2.controller:
    • 3.校验Token:
    • 4.开启登录拦截器
    • 5.加载拦截器

      cookie方式实现

      使用前端缓存cookie的方式实现,十分不安全

      后端:

      
          
          
              org.springframework.boot
              spring-boot-starter-web
          
      
      
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.*;
      import javax.servlet.http.Cookie;
      import javax.servlet.http.HttpServletResponse;
      @Controller
      public class LoginController {
          @GetMapping("/")
          public String index() {
              return "index";
          }
          @PostMapping("/login")
          public String login(@RequestParam("username") String username,
                              @RequestParam("password") String password,
                              HttpServletResponse response) {
              // 进行用户名和密码的验证逻辑
              if (isValidUser(username, password)) {
                  // 验证通过,创建一个Cookie保存用户登录信息
                  Cookie cookie = new Cookie("user", username);
                  cookie.setMaxAge(86400); // 设置Cookie有效期为1天
                  response.addCookie(cookie);
                  // 重定向到登录成功页面
                  return "redirect:/success";
              } else {
                  // 验证失败,返回登录页面
                  return "redirect:/?error=1";
              }
          }
          @GetMapping("/success")
          public String success() {
              return "success";
          }
          private boolean isValidUser(String username, String password) {
              // 在实际应用中,这里可以进行用户名和密码的验证逻辑,比如查询数据库或调用API等
              // 这里只是一个示例,始终返回true来模拟验证通过
              return true;
          }
      }
      

      前端:

      
      
      
        Cookie 示例
      
      
        

      Cookie 示例

      session的方式

      后端保存会话(redis),前端发信息

      
      
          
          
              org.springframework.boot
              spring-boot-starter-session
          
          
          
              org.springframework.boot
              spring-boot-starter-data-redis
          
      
      
      # Redis 连接配置
      spring.redis.host=localhost
      spring.redis.port=6379
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
      @SpringBootApplication
      @EnableRedisHttpSession
      public class MyApplication {
          public static void main(String[] args) {
              SpringApplication.run(MyApplication.class, args);
          }
      }
      

      实现session,Spring 会自动使用 Redis 来管理 HttpSession。

      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RestController;
      import javax.servlet.http.HttpSession;
      @RestController
      public class MyController {
          @GetMapping("/profile")
          public String getProfile(HttpSession session) {
              // 从会话中获取用户信息
              String username = (String) session.getAttribute("username");
              if (username != null) {
                  return "Username: " + username;
              } else {
                  return "Not logged in";
              }
          }
      }
      

      前端:

      // 后端返回的响应中包含 session ID
      const sessionID = '1234567890';
      // 前端将 session ID 存储在 LocalStorage 中
      localStorage.setItem('sessionID', sessionID);
      // 发送请求时手动将 session ID 携带在请求头中或请求参数中
      fetch('/profile', {
        headers: {
          'Authorization': 'Bearer ' + localStorage.getItem('sessionID')
        }
      })
      .then(response => response.json())
      .then(data => {
        if (data.success) {
          // 成功获取到用户资料信息
          console.log(data);
        } else {
          // 未登录,进行相应处理
          console.log('未登录');
        }
      });
      

      jwt方式实现

      特点:一次登录,到处畅通。

      使用sso微服务去认证,通过后保存token,再次验证时出示凭证即可获取登录信息。

      Spring Boot实现登录注册的三种基本方式,在这里插入图片描述,第1张

      1. 添加依赖

      
          com.auth0
          java-jwt
          3.8.3
      
      
          io.jsonwebtoken
          jjwt
          0.9.1
      
      

      2.controller:

          @RequestMapping("/login")
          public Map login(String userName, String password){
              Map map=new HashMap<>();
              try{
                  String token = Jwts.builder().setSubject(userName) //主题,可以放用户的详细信息
                          .setIssuedAt(new Date()) //token创建时间
                          .setExpiration(new Date(System.currentTimeMillis() + 60000)) //token过期时间
                          .setId("userId") //用户ID
                          //.setClaims(hashMap) //配置角色信息
                          .signWith(SignatureAlgorithm.HS256, "WuHan") //加密方式和加密密码
                          .compact();
                //  System.out.println("token:"+token);
                  map.put("code","1");
                  map.put("msg","success");
                  map.put("token",token);
                  map.put("user",userName);
              }catch (Exception e){
                  map.put("code","0");
                  map.put("msg","fail");
                  e.printStackTrace();
              }
              return map;
          }
      

      token示例如下:

      token:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4YyIsImlhdCI6MTU5MTE1NDQwNiwiZXhwIjoxNTkxMTU0NDY2LCJqdGkiOiJ1c2VySWQifQ.c7gCDgIQ_I40dIWRxyG4yd1xaZQyWflnC7kX2Uoc9H8
      

      token构成包含三个部分:

      • Header 头部
      • Payload 负载
      • Signature 签名

        注意事项:

        ①根据需求设计过期时间(1秒 =1000 毫秒 )

        ②因为我把时间设计到token里面了所以你可以测试每次产生的token不一样

        ③设置userId那一栏-我目前是写死了 setId(“userId”) ,你可以根据需求设计不同的值进去

        3.校验Token:

        try {
            JwtParser parser = Jwts.parser();
            parser.setSigningKey("WuHan");//解析 要和上面“暗号”一样
            Jws claimsJws = parser.parseClaimsJws(token);
            Claims body = claimsJws.getBody();
            String username = body.getSubject();
          //  Object role = body.get("role");
            return true;
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
        } catch (UnsupportedJwtException e) {
            e.printStackTrace();
        } catch (MalformedJwtException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        

        setSigningKey()与builder中签名方法signWith()对应,parser中的此方法拥有与signWith()方法相同的三种参数形式,用于设置JWT的签名key,用户后面对JWT进行解析。

        isSigned() 校验JWT是否进行签名。方法很简单,以分隔符" . ",截取JWT第三段,即签名部分进行判断。

        前端:

         
        //需要验证token的页面
            
        

        补充:

        window.sessionStorage(session级别):暂时储存,浏览器关闭之后会清除

        window.localStorage (namespace级别):本地储存,浏览器关闭之后依旧不会清除,只能人为删除

        4.开启登录拦截器

        /**
         * 登录拦截
         */
        @Component
        public class LoginInterceptor implements HandlerInterceptor {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                String token = request.getParameter("token");
                try {
                    JwtParser parser = Jwts.parser();
                    parser.setSigningKey("WuHan");
                    Jws claimsJws = parser.parseClaimsJws(token);
                    Claims body = claimsJws.getBody();
                    String username = body.getSubject();
                    Object role = body.get("role");
                    return true;
                } catch (ExpiredJwtException e) {
                    e.printStackTrace();
                } catch (UnsupportedJwtException e) {
                    e.printStackTrace();
                } catch (MalformedJwtException e) {
                    e.printStackTrace();
                } catch (SignatureException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }
                return false;
            }
            @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 {
            }
        }
        

        5.加载拦截器

        @Configuration
        public class AppConfig implements WebMvcConfigurer {
            @Resource
            private LoginInterceptor loginInterceptor;
            /**
             * 添加拦截器
             * @param registry
             */
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                //.execudePathPatterns()//可以添加不拦截的地址
                registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
            }
        }