当前位置: 首页>移动开发>正文

cookie、session、token

cookie、session理论

  • 为什么要设计cookie?
    HTTP 是无状态协议,它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求处理。但是为了实现一些有状态的情况,根据上次的请求来对下次请求处理。如登录认证等,就设计了cookie来在浏览器端管理状态。

  • cookie和session的区别?
    cookie保存在客户端浏览器,session保存在服务器。

  • cookie的属性

    cookie、session、token,第1张
    图解HTTP
  • cookie的种类
    内存cookie:特点在于cookie保存在内存中,浏览器关闭,cookie消失,属于非持久性cookie。
    磁盘cookie:特点在于cookie保存在磁盘中,设置一个过期时间,如果用户手动清除了cookie或者cookie已经到了过期时间,那么硬盘cookie才会被删除,否则就会一直存在。

  • cookie过期时间
    HTTP请求头未设置cookie到期时间expires属性:cookie存储在客户端的内存(浏览器占用的内存)中,不会写入磁盘。当浏览器关闭时,cookie将从此永久丢失。
    HTTP请求头设置cookie到期时间expires属性:存储在客户端的磁盘中,在指定的到期日期,cookie将从磁盘中删除。

  • cookie与session交互过程

    cookie、session、token,第2张
    网图
cookie、session、token,第3张
图解HTTP

当客户端浏览器第一次发请求给服务器时,当前的客户端cookie中没有会话session id,此时服务器会分配一个新的session,将session中的id存储到cookie中返回给客户端浏览器(通过响应头Set-Cookie字段),浏览器会缓存服务器响应的cookie(session id)。

当客户端浏览器第二次发请求给服务器时,当前的客户端会发送请求的请求头中携带cookie字段,里面存放上次的session id,那么服务器就去查找自己的session列表,这样服务器就可以识别出请求的浏览器为上次请求的浏览器,就辨清了身份。

  • 思考,浏览器会cookie过期,服务器session也会设置过期,两种情况
    cookie过期:浏览器发送给服务器请求不带cookie值,那么服务器会重新为其生成session id,便于下次请求传递。
    session过期:浏览器发送给服务器请求带cookie值,那么服务器会返回401,提示其没有权限,让其重新登陆。

  • 关闭浏览器则session过期的说法
    一些网站后台在响应浏览器的请求的时候,返回session id在cookie中,但是却没有指定expires过期时间字段,造成cookie只是存储在了浏览器的内存中,没有存到磁盘持久化,这样当浏览器关闭,那么内存被回收,丢失了存储session id的信息,再次访问服务器就找不到对应session了,产生了session丢失的假象,实际上session信息依然还在session列表中,只有到了过期时间或者删除了session才会让session消失。

servlet指定cookie过期时间

@GetMapping("/test/cookie")
public ResultModel<String> testCookie(HttpServletRequest request,
                                      HttpServletResponse response) {
    ResultModel<String> resultModel = new ResultModel();
    resultModel.setTime(TimeUtil.getNowTime());
    String sid = request.getHeader("Cookie");

    if (StrUtil.isBlank(sid)) {
        sid = UUID.randomUUID().toString().replace("-", "");
        Cookie cookie = new Cookie("sid", sid);
        cookie.setPath("/");
        cookie.setMaxAge(15);
        response.addCookie(cookie);
        log.info("新生成sid = " + sid);
        resultModel.setMsg("新生成sid = " + sid);
        resultModel.setRes(sid);
        return resultModel;
    }

    log.info("之前生成的sid = " + sid);
    resultModel.setMsg("之前生成的sid = " + sid);
    resultModel.setRes(sid);

    return resultModel;
}
cookie、session、token,第4张

操作1:第二次请求,浏览器会自动带上Cookie值。

cookie、session、token,第5张

操作2:关闭浏览器,再打开浏览器请求同一个url,依然还会自动带上Cookie值

操作3:不停的刷新浏览器,发现Cookie值一直不变,在过去15s之后,发现浏览器的cookies消失了,再刷新生成了一个新的Cookie值。

Session验证登录

@GetMapping("/test/api")
public ResultModel<String> testApi(HttpServletRequest request) {
    ResultModel<String> resultModel = new ResultModel<>();
    resultModel.setTime(TimeUtil.getNowTime());
    UserInfo userInfo = (UserInfo) request.getSession().getAttribute("user");

    if (Objects.isNull(userInfo)) {
        resultModel.setMsg("您还未登录");
        return resultModel;
    }

    resultModel.setMsg("执行api service方法");
    return resultModel;
}

@GetMapping("/test/logout")
public ResultModel<String> testLogout(HttpServletRequest request) {
    ResultModel<String> resultModel = new ResultModel<>();
    resultModel.setTime(TimeUtil.getNowTime());
    request.getSession().removeAttribute("user");
    resultModel.setMsg("用户已退出");
    return resultModel;
}

@PostMapping("/test/login")
public ResultModel<UserInfo> testLogin(@RequestHeader String username,
                                         @RequestHeader String password,
                                         HttpServletRequest request) {
    ResultModel<UserInfo> resultModel = new ResultModel<>();
    resultModel.setTime(TimeUtil.getNowTime());

    /**
     * 通过数据库去查询username和password的正确性
     * 通过new一下作为查询结果了
     */
    if (username.equals("zhangsan") && password.equals("123456")) {
        HttpSession session = request.getSession();
        UserInfo userInfo = new UserInfo(username, password, 30, "男");
        session.setAttribute("user", userInfo);
        // 设置session的过期时间
        session.setMaxInactiveInterval(10);
        resultModel.setMsg("用户 " + username +
                "登录成功,新生成的JSESSIONID = " + session.getId());
        resultModel.setRes(userInfo);
        return resultModel;
    }

    resultModel.setMsg("登录失败:用户名和密码错误");
    return resultModel;
}

setMaxInactiveInterval方法:session的过期时间,单位为秒,超过指定的时间,就会自动删除session中存储的值。

第一次登录会自动生成JSESSIONID响应 :

cookie、session、token,第6张

session过期之后再登录,会自动刷新JSESSIONID,返回响应:

cookie、session、token,第7张
  • 我们发现session的操作其实也是基于cookie来实现的。
  • 后面为了解决每次业务操作api都要进行校验,我们可以使用过滤器来方便我们的校验。

token设计

  • token的好处:
    token自身就携带了身份验证的信息,不需要服务器存储session,减轻服务器压力。
    session进行身份验证依赖cookie,不适合移动端,相反token可以被客户端存储,还可以跨语言使用。
    session会存在跨域的问题,但是token就不会了。

基于JWT实现token

  • token工具类:
public class JwtUtil {


    public static final String SECRET = "haha";

    public static <V> String createJWT(Map<String, Object> map, int expireTimes, int expireUnit, SignatureAlgorithm algorithm) {
        JwtBuilder builder = Jwts.builder();
        builder.setClaims(map);
        builder.signWith(algorithm, SECRET);
        Calendar instance = Calendar.getInstance();
        instance.add(expireUnit, expireTimes);
        builder.setExpiration(instance.getTime());
        return builder.compact();
    }

    public static String createJWT(Map<String, Object> map, int expireTimes) {
        return createJWT(map, expireTimes, Calendar.SECOND, SignatureAlgorithm.HS256);
    }

    public static <V> String createJWT(String key, String value, int expireTimes) {
        Map<String, Object> map = new HashMap<>();
        map.put(key, value);
        return createJWT(map, expireTimes);
    }

    public static Claims parseJWT(String jwt){
        return Jwts.parser().
                setSigningKey(SECRET).parseClaimsJws(jwt).getBody();
    }

    public static void main(String[] args) {
        String jwt = createJWT("1", "sunpy", 60);
        System.out.println(jwt);
        System.out.println(parseJWT(jwt).get("1"));
        parseJWT(jwt).entrySet().forEach(entry -> {
            System.out.println("key: " + entry.getKey() + " value: " + entry.getValue());
        });
    }
}

https://www.xamrdz.com/mobile/4n51995692.html

相关文章: