在开发中,最常使用的通信协议就是HTTP协议,用HTTP进行客户端与服务器的数据交换,每次HTTP请求由客户端(Web浏览器、手机App等)主动发起,服务器端被动接收并对请求进行处理后响应给客户端,但由于HTTP的请求是无状态的,即每次请求都是一个新的请求,如果没有在传输过程中携带附加的认证信息,服务器端是无法识别正在与其通信的客户端的。那么在用HTTP协议通信的过程中,识别通信客户端的方式都有哪些呢?一般可以在请求头中使用Cookie、Authorization等字段让服务器端知道是哪个客户端正在与之进行通信。
Cookie与Session
Cookie是存储在浏览器的一小块数据,一般会有个数和大小限制。服务器端可以在通信的过程中通过响应头中Set-Cookie字段设置要在浏览器存储的Cookie数据(可以设置路径(path)与存活时间(expires))。之后浏览器的每次请求都会默认携带上Cookie数据。如下图是访问百度时的HTTP请求详情:可以看到,在首次访问之后响应头部数据Response Headers中的Set-Cookie当中的键值对数据。之后我在刷新页面,在Request Header中就看到了Cookie这个请求头了,如果没有禁止使用Cookie,浏览器在发送请求的时候就会自动将Cookie发送给服务器。这样服务器端就可以根据Cookie当中的相关数据做一些其他的事情了:比如识别客户端,根据客户端的浏览记录进行推荐等。
开发人员也可以通过JS操作浏览器设置Cookie,根据客户的浏览设置然后发给服务器端,让后端做相应的处理,然后作出响应。
下面的代码展示了服务端如何向浏览器植入Cookie
@GetMapping("/userInfo")
public void cookieTest(HttpServletResponse response) {
Cookie cookie = new Cookie("user", "stefan");
cookie.setPath("/");
cookie.setMaxAge(10);
response.addCookie(cookie);
}
请求后的结果:浏览器中已经存在Cookie值了。
在Cookie当中,数据是存在客户端浏览器当中,用户可以看到这些信息,所以Cookie当中一般不会存储敏感的信息,存敏感的信息要进行加密处理。那么有没有办法让这些信息存储在服务器端呢?有的,那就是使用Session,Session是服务器当中的一块内存,可以存储键值对。其运作方式与Cookie相同,客户端存储Key为JSESSIONID的Cookie。如下面这段程序显示了在Session当中写入验证码,并在下次请求时从Session当中获取验证码。
@GetMapping("/code")
public void code(HttpSession session, HttpServletResponse response) {
GifCaptcha lineCaptcha = CaptchaUtil.createGifCaptcha(116, 36, 6);
session.setMaxInactiveInterval(300);
session.setAttribute("key", lineCaptcha.getCode());
try {
ServletOutputStream outputStream = response.getOutputStream();
lineCaptcha.write(outputStream);
outputStream.close();
} catch (Exception e) {
log.error("error generate code{}", e.getMessage());
}
}
@GetMapping("/getCode")
public String getCode(HttpSession httpSession, HttpServletResponse response) {
String code = (String) httpSession.getAttribute("key");
return code;
}
具体的运行结果如下图:
所以Session本质上时HTTP协议当中的Cookie,只是关键信息存储的位置由客户端存储转变为由服务器端进行存储,安全系数会比较高,常见的应用场景是可以识别用户是否登录。
Token
我们知道Cookie只有浏览器当中才有,并且有个缺点是用户可以在浏览器禁用Cookie,一旦Cookie被禁用,就无法靠Session识别客户端了,还有考虑到一些用HTTP协议进行通信的移动端App的身份认证,所以现在主流的方式是在HTTP请求头中Authorization设置Bearer token,token是由服务器端生成并颁发给客户端的认证凭证,看客户端是否具有某些权限,如下图所示:
个人博客:https://www.kangpeiqin.cn/#/index