不知道大家是否想过这样一个问题,比如说我们登陆淘宝之后,点击订单,点击购物车,这些都是自己的信息。通过前面的学习,我们也知道 HTTP 协议是无状态的,我们与淘宝的服务器之间,只是通过一串串字节在交流。我们发送请求,就是发给服务器一串字节流,服务器收到后作出响应,也返回一串字节流。当我们点击「购物车」,点击「订单」他怎么知道是「我」在查看购物车信息,而不是张三在查看购物车呢?

我们想到一种笨拙的解决办法:当我们点击购物车的时候,系统让你登陆账号密码,登陆之后就能正确访问你的信息了。当我们点击其他信息时,比如「订单」,系统也让你输入账号密码,这样订单信息也能正确访问了。这种方法是一种解决办法,但是给用户带来的体验很不好。cookie 就是用来维持登陆状态的东西。

Cookie 是什么 

简单来说就是一串字符串数据,用来区分和辨别不同用户。可以理解为「身份证」,通过身份证这一串数据,我们就能知道是谁在访问服务器。当然这一字符串可能还会包含,Cookie 的过期时间,以及一些安全协议等等。

Cookie 如何维持状态当我们第一次登陆一个网站的时候,我们填写好自己的账号密码信息,向服务器发送登陆请求。服务器根据你传过来的账号密码进行判断,倘若账号密码正确,服务器就会返回登陆成功的信息,并且在返回的 response header 中使用 Set-Cookie  参数,设置一段随机字符串 Cookie。

当我们有了 Cookie 之后,我们发出去的所有请求,浏览器都会帮我们把 Cookie 字符串带上,服务器就根据 Cookie 信息来辨别用户,返回正确的用户信息。

使用 Java 代码获取 Cookie 信息

public class Crawler {
 
    private static final String COOKIE_URL = "http://47.91.156.35:8000/auth/login";
    private static final String MESSAGE_URL = "http://47.91.156.35:8000/auth";
    private static final CloseableHttpClient httpclient = HttpClients.createDefault();
 
    public static String loginAndGetResponse(String username, String password) throws IOException {
 
        HttpPost httpPost = new HttpPost(COOKIE_URL);
        httpPost.addHeader("Content-Type", "application/json");
        httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36");
 
        Map<String, String> map = new HashMap<>(16);
        map.put("username", username);
        map.put("password", password);
 
        HttpEntity entity = new StringEntity(JSON.toJSONString(map));
        httpPost.setEntity(entity);
        CloseableHttpResponse loginResponse = httpclient.execute(httpPost);
 
        String result = getMessageByCookie(loginResponse.getFirstHeader("Set-Cookie").getValue());
        loginResponse.close();
 
        return result;
    }
 
    public static String getMessageByCookie(String cookie) throws IOException {
        HttpGet httpGet = new HttpGet(MESSAGE_URL);
        httpGet.addHeader("Cookie", cookie);
        CloseableHttpResponse response = httpclient.execute(httpGet);
 
        HttpEntity entity1 = response.getEntity();
        InputStream is = entity1.getContent();
        // 设置解析编码为UTF-8
        String html = IOUtils.toString(is, "UTF-8");
        EntityUtils.consume(entity1);
        response.close();
        return html;
    }
}
 

使用给定的用户名 username 和密码 password 进行模拟登录,然后获取服务器返回的 Cookie的值,并把获取到的 Cookie 带到下一次的请求中去访问个人信息。

首先新建一个 HttpPost 对象,添加所需的头部信息。 Content-type 告诉服务器我们要给服务器发送的数据类型。 User-Agent 让我们模拟浏览器的方式去访问,避免被服务器屏蔽请求。

使用 Map 对象将我们得账号密码存储起来,接着使用 JSON 工具转化为字符串,放到请求体中,执行 POST 请求,把返回的头部信息 Set-Cookie 的值拿到。

使用 getMessageByCookie 方法,把获取到的 Cookie 值当做参数传入。方法中发送了一个 HttpGet 请求,把Cookie加到请求头中,发送到服务器,并把返回的 body 数据转化为字符串,返回去。

这样就是一次使用获取 Cookie ,并使用 Cookie 的简单访问。