クッキーは何のためにあるのでしょうか?
思考の質問 1 - レンガを投げて翡翠を引き寄せる
特定の Web サイトにアクセスしたときに、その Web サイトに最後にログインした時刻がわかりますが、
ユーザーごとに最終ログイン時刻が異なることに注意する必要があります。これはどのように実現されますか?
思考の質問 2 - レンガを投げて翡翠を誘導する
ショッピング Web サイトにアクセスしたときに、以前に閲覧した商品が表示されますか? ユーザーごとに閲覧した商品は異なるはずです。これはどのように実現されますか?
解決策 - Cookie テクノロジー
Cookie (小さい Cookie) はクライアント側のテクノロジであり、サーバーは各ユーザーのデータを Cookie の形式でユーザーのそれぞれのブラウザに書き込みます。ユーザーがブラウザを使用してサーバー内の Web リソースにアクセスすると、独自のデータが持ち込まれます。このようにして、Web リソースはユーザー自身のデータを処理します。【簡易図】
クッキーの紹介
二人はクッキーを言った
- Cookieとは、ログイン名や閲覧履歴などのユーザーの情報をクライアント側で保存するサーバーであり、Cookieの形式で保存することができます。
- Cookie 情報は Cookie (クッキー) のようなもので、データ量は大きくなく、必要なときにサーバーがクライアントのブラウザから読み込むことができます。これは図から理解できます。
Cookieは何に使用できますか?
- 最終ログイン時刻などの情報を保存する
- ユーザー名、パスワードを保存し、一定期間は再ログイン不要
- Web サイトのサービスやコンテンツのカスタマイズなど、Web サイトのパーソナライズ。
Cookie はローカル ブラウザに保存されます。!!
クッキーの基本的な使い方
ドキュメンテーション
https://docs.oracle.com/javaee/7/api/
クッキーの一般的な方法
-
図に示すように、Cookie はテーブル (KV) に似ており、2 つの列に分かれており、1 つは名前、もう 1 つは値で、データ型は文字列です。
-
Cookieの作成方法(サーバー側で作成)
Cookie c = new Cookie(String name,String val);
c.setMaxAge();//保存时间
- クライアントにCookieを追加する方法
response.addCookie(c);
- Cookieの読み取り方法(サーバー側のCookie情報を読み取る)
request.getCookies();
Cookie の基礎となる実装メカニズム - Cookie の作成と読み取り
サーバー側での Cookie の作成
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @ClassName CreateCookie
* @Description TODO
* @Author zephyr
* @Date 2022/12/18 22:37
* @Version 1.0
*/
@WebServlet(name = "CreateCookie", value = "/createCookie")
public class CreateCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========CreateCookie被调用==========");
//1. 创建一个Cookie对象
/**
* 1) username 该cookie的名字,唯一的,可以理解成key
* 2) zephyr 该cookie的值
* 3) 可以创建多个cookie对象
* 4) 这是这个cookie在服务器端,还没有到浏览器
*/
Cookie cookie = new Cookie("username", "zephyr");
response.setContentType("text/html;charset=utf-8");
//2. 将cookie发送给浏览器,让浏览器将该cookie保存起来
response.addCookie(cookie);
PrintWriter writer = response.getWriter();
writer.println("<h1>创建cookie成功!<h1>");
writer.flush();
writer.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
サーバー側の読み取りクッキー
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
* @ClassName ReadCookies
* @Description 演示:读取从客户端发送来的cookie信息
* @Author zephyr
* @Date 2022/12/19 10:47
* @Version 1.0
*/
@WebServlet(name = "ReadCookies", value = "/readCookies")
public class ReadCookies extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========CreateCookie被调用==========");
//1. 通过Request对象读取所有Cookie信息
Cookie[] cookies = request.getCookies();
//2. 遍历Cookie
if (cookies != null && cookies.length > 0){
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + " = " + cookie.getValue());
}
}
//Cookie: JSESSIONID=BA235330CCE65FE095ED5EFB37B3A113; username=zephyr
//3. 给浏览器返回信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h1>读取cookie信息成功<h1>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
JSESSIONID の用途は何ですか?
セッションとはセッションという意味です。
JSESSIONID はセッションの一意の識別子です。
Cookieの適用例
指定されたクッキーを読み取ります
ツール クラスを横断して、指定された Cookie を見つけます。
CookieUtils.java
package com.hspedu.cookie;
import javax.servlet.http.Cookie;
/**
* @ClassName CookieUtils
* @Description 对Cookie数组进行过滤
* @Author zephyr
* @Date 2022/12/19 11:40
* @Version 1.0
*/
public class CookieUtils {
public static Cookie readCookieByName(String cookieName, Cookie[] cookies) {
//如果传输参数不正确就返回null
if (cookieName == null || "".equals(cookieName) || cookies == null || cookies.length == 0) {
return null;
}
for (Cookie cookie : cookies
) {
if (cookieName.equals(cookie.getName())) {
return cookie;
}
}
//没找到就返回null
return null;
}
}
クッキーを変更する
要件: 指定された Cookie を指定して、Cookie を検索し、見つかった場合は値を jyl-hi に変更し、見つからなかった場合は、Cookie が見つからないことを示すプロンプトを表示します。
UpdateCookie.java
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
* @ClassName UpdateCookie
* @Description TODO
* @Author zephyr
* @Date 2022/12/19 11:59
* @Version 1.0
*/
@WebServlet(name = "UpdateCookie", value = "/updateCookie")
public class UpdateCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========UpdateCookie被调用==========");
//1. 根据name,查找cookie
String cookieName = "email";
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName(cookieName, cookies);
if (cookie == null){
System.out.println("当前访问服务器的客户端没有该cookie");
} else {
cookie.setValue("jyl-hi");
//2. 遍历cookie查看值
for (Cookie cookie_ : cookies) {
System.out.println(cookie_.getName() + " = " + cookie_.getValue());
}
//3. cookie返回给浏览器
response.addCookie(cookie);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
setValue を使用して Cookie の値をリセットした後は、必ず
response.addCookie(cookie)
Cookie を返してください。
新しく作成された Cookie がブラウザの既存の Cookie と同じ名前である場合、その Cookie は上書きされます。
Cookieのライフサイクル
導入
- Cookie のライフサイクルとは、Cookie が破棄 (削除) されるタイミングを管理する方法を指します。
setMaxAge()
- 正の数。指定された秒数後に期限切れになることを示します。
- 負の数値は、ブラウザを閉じるときに Cookie が削除されることを意味します (デフォルト値は -1)。
- 0、Cookie をすぐに削除することを意味します
アプリケーション
Cookie のライフサイクルをデモンストレーションする
System.out.println("==========CookieLive被调用==========");
//演示创建一个cookie,生命周期为60s
Cookie cookie = new Cookie("job", "java");
//1. 从创建该cookie开始计时,60s后就无效了
//2. 浏览器根据创建时间,计时到60s就认为该cookie无效
//3. 如果该cookie无效,那么浏览器在发出http请求时,就不在携带该cookie
cookie.setMaxAge(60);
response.addCookie(cookie);
CookieLive にアクセスして、 に戻りますSet-Cookie: job=java; Max-Age=20; Expires=Mon, 19-Dec-2022 04:51:49 GMT
。60 秒後にこの Cookie を無効にする (保持しない) ようにブラウザに指示します。
60 秒後、ブラウザはジョブ Cookie なしで http リクエストをサーバーに送信します。
デモでは Cookie を削除します
System.out.println("==========CookieLive被调用==========");
//演示删除一个cookie:username
//1. 先得到这个cookie
Cookie usernameCookie = CookieUtils.readCookieByName("username", request.getCookies());
//2. 将其的生命周期设置为0
usernameCookie.setMaxAge(0);
//3. 通知浏览器
response.addCookie(usernameCookie);
ブラウザ側でパケットをキャプチャすると、応答ヘッダーに次の内容が表示されますSet-Cookie: username=zephyr; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT
。
すると、ブラウザのCookieが削除されていることがわかります。
ライフサイクルを設定しないとどうなるか
ただし、ライフ サイクルが設定されていない場合、デフォルトはsetMaxAge(-1)
セッション レベルのライフ サイクルです。これは、ブラウザを閉じるときに Cookie が削除されることを意味します。
有効な Cookie パス
- Cookie有効パス パス設定
- Cookie の path 属性は、どの Cookie をサーバーに送信できるかを効果的にフィルタリングできます。どれが掲載されていないのか。パス属性は、要求されたアドレスによって効果的にフィルタリングされます。
- ルールは次のとおりです
アプリケーション
System.out.println("==========CookiePath被调用==========");
//1. 创建2个cookie
Cookie bandCookie = new Cookie("band", "Gelneryus");
Cookie instrumentCookie = new Cookie("instrument", "Guitar");
//2. 设置不同的有效路径
bandCookie.setPath(request.getContextPath()); // ContextPath = /cs
// instrumentCookie的有效路径是 /cs/ins
instrumentCookie.setPath(request.getContextPath() + "/ins");
//3. 保存到浏览器
response.addCookie(bandCookie);
response.addCookie(instrumentCookie);
//4. 给浏览器返回信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h1>设置cookie路径成功<h1>");
宿題: ログインアカウントを自動的に入力します
- ユーザー名が hspedu でパスワードが 123456 の場合、ユーザーは正当であるとみなされ、ログインは成功します。それ以外の場合、ログインは無効です。
- ログインに成功すると、3 日以内にログインしたユーザーはログイン名を自動的に入力できることを認識する必要があります。
- ログイン ページは HTML ではなくサーブレットを使用して返される必要があります
ログイン ログイン ページ (サーブレットとして記述)
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @ClassName Login
* @Description TODO
* @Author zephyr
* @Date 2022/12/19 16:05
* @Version 1.0
*/
@WebServlet(name = "Login", value = "/login")
public class Login extends HttpServlet {
HttpServletRequest request = null;
HttpServletResponse response = null;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========Login被调用==========");
this.request = request;
this.response = response;
//先读取cookie,看看cookie里有没有username和pwd
Cookie[] cookies = request.getCookies();
Cookie usernameCookieRead = CookieUtils.readCookieByName("username", cookies);
Cookie pwdCookieRead = CookieUtils.readCookieByName("pwd", cookies);
if (usernameCookieRead != null && pwdCookieRead != null) {
//cookie存在
showLoginHtml(usernameCookieRead.getValue(), pwdCookieRead.getValue());
} else {
showLoginHtml("", "");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
public void showLoginHtml(String username, String pwd) throws ServletException, IOException{
String content = "<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <base href=\"/cs/\">\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>登录界面</title>\n" +
"</head>\n" +
"<body>\n" +
"<h1>用户登录界面</h1>\n" +
"<form action=\"loginServlet\" method=\"get\">\n" +
" 用户名:<input type=\"text\" name=\"username\" value=\""+username+"\"><br>\n" +
" 密码:<input type=\"text\" name=\"pwd\" value=\""+pwd+"\"><br>\n" +
" <input type=\"submit\" value=\"登录\">\n" +
"</form>\n" +
"\n" +
"</body>\n" +
"</html>";
if (request != null && response != null){
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println(content);
writer.flush();
writer.close();
}
}
}
ログインサーブレット
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @ClassName LoginServlet
* @Description TODO
* @Author zephyr
* @Date 2022/12/19 15:13
* @Version 1.0
*/
@WebServlet(name = "LoginServlet", value = "/loginServlet")
public class LoginServlet extends HttpServlet {
String correctUserName = "jingyl";
String correctPwd = "123456";
HttpServletRequest request = null;
HttpServletResponse response = null;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========LoginServlet被调用==========");
this.request = request;
this.response = response;
if (checkForm()){
showSuccess();
} else {
showFail();
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/**
* 返回登陆成功的信息
*/
public void showSuccess() throws ServletException, IOException {
//通知浏览器已经写入cookie
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>登录成功!<h1>");
}
/**
* 返回登陆失败的信息
*/
public void showFail() throws ServletException, IOException {
//通知浏览器已经写入cookie
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>登录失败!<h1>");
}
public boolean checkForm() throws ServletException, IOException {
//读取表单里的username和pwd
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
if (username.equals(correctUserName) && pwd.equals(correctPwd)) {
//如果账号密码正确则保存在浏览器的cookie
//创建cookie保存用户名和密码
Cookie usernameCookie = new Cookie("username", username);
Cookie pwdCookie = new Cookie("pwd", pwd);
//生命周期为3天
usernameCookie.setMaxAge(60 * 60 * 24 * 3);
pwdCookie.setMaxAge(60 * 60 * 24 * 3);
response.addCookie(usernameCookie);
response.addCookie(pwdCookie);
return true;
} else {
return false;
}
}
}
Cookie に関する考慮事項と詳細
Cookie は 1 種類の情報のみを識別でき、情報を識別するための名前 (NAME) と設定値 (VALUE) が少なくとも含まれます。- WEB サイトは複数の Cookie をブラウザに送信でき、ブラウザは複数の WEB サイトから提供された Cookie を保存することもできます。
- Cookie の総数に制限はありませんが、ドメイン名ごとの Cookie の数と各 Cookie のサイズには制限があり (ブラウザごとに制限が異なりますので、注意してください)、Cookie は大量の情報を保存するのには適していません。データの。
- Cookie を削除するときは、パスが一貫している必要があり、そうでない場合は削除されないことに注意してください。
- Java サーブレットの Cookie の中国語文字化けを解決する [コードデモ EncoderCookie.java ReadCookie2.java]
中国語の Cookie 情報を保存することはお勧めできません。文字化けする可能性がありますが、URL エンコードとデコードによって解決できます。
中国語のクッキー文字化け問題を解決
中国語の Cookie を直接保存すると、エラーが報告されます
- 中国語は次のように
URLEncoder.encode()
エンコードできます
System.out.println("==========EncoderCookie被调用==========");
//1. 如果直接错放中文的cookie会报错
//2. 通过将中文编码成 URL 编码
String company = URLEncoder.encode("景风眠教育", "utf-8");
Cookie cookie = new Cookie("company", company);
response.addCookie(cookie);
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>EncoderCookie被成功调用[中文乱码测试]<h1>");
writer.flush();
writer.close();
- によって
URLDecoder.decode()
デコードされました
System.out.println("==========EncoderCookie被调用==========");
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName("company", cookies);
System.out.println(cookie.getName() + " = " + cookie.getValue());
System.out.println("===========解码后===========");
String decode = URLDecoder.decode(cookie.getValue());
System.out.println(cookie.getName() + " = " + decode);
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>DecoderCookie被成功调用[中文解码测试]<h1>");
writer.flush();
writer.close();