关于登录方式cookie,session,token

JWT全称JSON Web Token,由三部分组成: header(头)、payload(载体)、signature(签名)。 随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高,因此慢慢发展成为token的方式做登录身份校验,然后通过token去取redis中的缓存的用户信息,随着之后jwt的出现,校验方式更加简单便捷化,无需通过redis缓存,而是直接根据token取出保存的用户信息,以及对token可用性校验,单点登录更为简单。
通过token去取redis中的缓存的用户信息
    @Autowired
    RedisTemplate redisTemplate ;
    @Override
    public String login(LoginUser loginUser) {
        String cacheKey =UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(cacheKey ,loginUser.toString());
        return  cacheKey ;
    }
    public  void testLogin(String cacheKey){
        redisTemplate.opsForValue().get(cacheKey);
    }

通过Session

Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的信息将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话,或者 Session 超时失效时会话结束。也就是说,session 的作用是能够让服务器在某一用户登录之后,用户进行的所有操作都保持在同一会话之内,这样就能够记住用户的状态,并且能记住用户在这次会话中进行的一系列操作和保存的信息。

session 存储在服务器端,session 是用来存储信息的,在 cookie 里面插入的只是 session id,是识别某一 session 的唯一标识。

事实上,服务器在第一次获取 session 即调用 request.getSession() 的时候,服务器会创建一个 session 对象(session 是一个集合,并且是一个map集合),并且存入服务器的 session 集合中以 sessionId 为标识键,也就是说根据 sessionId 即可取到对应 session 的引用。同时也会创建一个键名为 JSESSIONID 的 cookie 并且返回给浏览器,该 cookie 的值即为 sessionId。

如果客户访问同一域的其他 Servlet,这个存储着 sessionId 的 cookie 就会跟着请求上传到服务器。此时如果请求的另一个Servlet也要使用 session,服务器会自动检查有没有这个保存 sessionId 的 cookie,如果有则直接到 session 集合中取对应的 session 引用返回给要使用的Servlet。所以说,在同一会话当中,不管请求哪个Servlet,拿到的都是同一个session。

我们这里所说的session都是基于cookie机制来实现的,所以可以说,session的实现是依赖于cookie的。

通过Session_id 追终, 客户端下次携带上JESSIONID的cookie来辨别 注意是自动携带的
public String loginBySession(HttpSession session,LoginUser loginUser){ session.setAttribute("user",loginUser);
     session.getId();
return "success"; } public void testLoginBySession(HttpSession httpSession){ LoginUser loginUser = (LoginUser) httpSession.getAttribute("user"); }

通过Cookie的方式去登录

cookie存储在客户端,用到的时候直接携带上就可以

 public  String loginCookie(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        String telephone=null;
        for(Cookie cookie: cookies){
            if("cook_telephone".equals(cookie.getName())){
                telephone=  cookie.getValue();
            }
        }
        return telephone;
    }

这些可能都不需要详细了解,需要详细了解JWT,参考

https://segmentfault.com/a/1190000012874052?utm_source=sf-similar-article

https://www.jianshu.com/p/e34a579c63a0

 头部 head

声明类型声明加密算法:

//头部信息
eyJhbGciOiJIUzI1NiJ9 用在线网站解密后 {"alg":"HS256"}
eyJhbGciOiJub25lIn0 {"alg":"none"}

 

载荷 payload

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

标准中注册的声明 (建议但不强制使用) :

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

公共的声明
公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明
私有声明是提供者和消费者所共同定义的,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息

 

       String token = Jwts.builder().setSubject("暴富")
//payload
.claim("head_img", loginUser.getHeadImg())
.claim("id", loginUser.getId())
.claim("name", loginUser.getName())
.claim("mail", loginUser.getMail())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
// .signWith(SignatureAlgorithm.HS256, SECRET) // 这个盐加hash生成
.compact();


eyJzdWIiOiLmmrTlr4wiLCJpYXQiOjE2MzgzNjQ2OTYsImV4cCI6MTY0MDExNzcyOH0 解密: {"sub":"暴富","iat":1638364696,"exp":1640117728}
eyJzdWIiOiLmmrTlr4wiLCJpYXQiOjE2MzgzNjQ4OTMsImV4cCI6MTY0MDExNzkyNn0 解密: {"sub":"暴富","iat":1638364893,"exp":1640117926}

signature: 签证

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)
  • payload (base64后的)
  • secret

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

pgyvlr_1uCDnPn-Iafb-xAumQKQ-AqLaWOnILiVk8b8  加了盐之后无法进行解析 
检验token信息
public static Claims checkJWT(String token) {
        try {
            final Claims claims = Jwts.parser()
                    .setSigningKey(SECRET)
//在头部加一个token信息,防止正对新破解 .parseClaimsJws(token.replace(TOKEN_PREFIX,
"")).getBody(); return claims; } catch (Exception e) { log.info("jwt token解密失败"); return null; } }

使用到的包是 

<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

暂时写到这里,之后有更详细的解释



 

 



 

posted @ 2021-12-01 16:55  天道酬勤312  阅读(271)  评论(0)    收藏  举报