Cookie工作原理
Cookie演示
我们启动服务器,演示一下Cookie 的效果:
服务器:
客户端:(第一次设置 Cookie)
第二次就会自己加上Cookie信息,在这里存的就是用户的信息:
我们在看看服务器:
我们还可以通过Fiddler抓包看看我们构造的响应和请求:
再次理解Cookie:Cookie是可以有多个的也不是一成不变的,比如我们演示一个多次访问cookieTime,每次都获取到不同的时间戳作为Cookie。
第一次访问:
第二次访问:
在这里只是修改了 time 这个cookie, user 还是登录用户的信息,是不收影响的。
如何使用cookie 完成一次登录过程,我们得看看下边这个代码是如何实现,不仅仅是浏览器,服务器也要做出相应的逻辑实现。
V3版本http 服务器
主要工作:
1、支持返回一个静态的 html 文件
2、解析处理 cookie(把 cookie处理成键值对结构)
3、解析处理 body (把body 中的数据处理成键值对结构)
4、实现完整的登录功能(session 的简单实现)
在这里我说一下主要代码:
private void doPost(HttpRequest request, HttpResponse response) {
// 2. 实现 /login 的处理
if (request.getUrl().startsWith("/login")) {
// 读取用户提交的用户名和密码
String userName = request.getParameter("username");
String password = request.getParameter("password");
// System.out.println("userName: " + userName);
// System.out.println("password: " + password);
// 登陆逻辑就需要验证用户名密码是否正确.
// 此处为了简单, 咱们把用户名和密码在代码中写死了.
// 更科学的处理方式, 应该是从数据库中读取用户名对应的密码, 校验密码是否一致.
if ("fwh".equals(userName) && "123".equals(password)) {
// 登陆成功
response.setStatus(200);
response.setMessage("OK");
response.setHeader("Content-Type", "text/html; charset=utf-8");
// 原来登陆成功, 是给浏览器写了一个 cookie, cookie 中保存的是用户的用户名.
// response.setHeader("Set-Cookie", "userName=" + userName);
// 现有的对于登陆成功的处理. 给这次登陆的用户分配了一个 session
// (在 hash 中新增了一个键值对), key 是随机生成的. value 就是用户的身份信息
// 身份信息保存在服务器中, 此时也就不再有泄露的问题了
// 给浏览器返回的 Cookie 中只需要包含 sessionId 即可
String sessionId = UUID.randomUUID().toString();
User user = new User();
user.userName = "fwh";
user.age = 20;
user.school = "邮电";
sessions.put(sessionId, user);
response.setHeader("Set-Cookie", "sessionId=" + sessionId);
response.writeBody("<html>");
response.writeBody("<div>欢迎您! " + userName + "</div>");
response.writeBody("</html>");
} else {
// 登陆失败
response.setStatus(403);
response.setMessage("Forbidden");
response.setHeader("Content-Type", "text/html; charset=utf-8");
response.writeBody("<html>");
response.writeBody("<div>登陆失败</div>");
response.writeBody("</html>");
}
}
}
session 工作原理
response.setHeader("Set-Cookie", "userName=" + userName);
如果我们用这行代码,借助 Cookie来实现登录保持功能,这样做是不太好的,用户信息在 Cookie中,每次数据传输都要把这个 Cookie 再次发给服务器,这就意味着 Cookie 中的信息很容易泄露,甚至可以伪造,绕开登录~~所以我们就需要session了!
在服务器登录成功时,把用户信息保存在一个 hash 表中(value),同时生成一个 key(这个key 是一个唯一的字符串),sessionId,最终把 sessionId 写会到 cookie 中就好了。后续访问页面的时候,Cookie 中的内容就是 sessionId,sessionId是一个没有规律的字符串,提高了安全性。服务器可以通过 sessionId 进一步找到用户的相关信息。
String sessionId = UUID.randomUUID().toString();
这行代码就会生成一个随机的字符串,每次1调用都会生成不同的。
刚开始是没有的,响应通过 set-Cookie 来保存:
接下来访问就可以获得:
通常session 是要搭配一个 过期机制,来记录线程何时创建,何时过期,如果过期也需要你重新登录,不同的网站它自己设定的过期时间也是不同的。
Cookie 和 session 的关系
- 都是为了实现客户端与服务端交互而产出
- Cookie是保存在客户端,缺点易伪造、不安全
- Session是保存在服务端,会消耗服务器资源
- Session实现有两种方式:Cookie和URL重写
参考:深入理解HTTP协议
Session 管理及Cookie 应用
基于表单认证的标准规范尚未有定论,一般会使用Cookie 来管理Session(会话)。
- 步骤一:客户端把用户ID 和密码等登录信息放入报文的实体部分,通常是以POST 方法把请求发送给服务器。而这时,会使用HTTPS 通信来进行HTML 表单画面的显示和用户输入数据的发送。
- 步骤二:服务器会发放用以识别用户的Session ID。通过验证从客户端发送过来的登录信息进行身份认证,然后把用户的认证状态与Session ID 绑定后记录在服务器端。
- 步骤三:客户端接收到从服务器端发来的Session ID 后,会将其作为Cookie 保存在本地。下次向服务器发送请求时,浏览器会自动发送Cookie,所以Session ID 也随之发送到服务器。服务端可通过验证接收到的Session ID 识别用户和其认证状态。
另外,不仅基于表单认证的登录信息及认证过程都无标准化的方法,服务器端应如何保存用户提交的密码等登录信息等也没有标准化。
参考:《图解HTTP》