Cookie
what
服务器跟踪用户信息的技术称为会话技术。
- Cookie是一种会话技术,它用于将会话过程中的数据保存到用户的浏览器中,
- 过程:
- 当用户通过浏览器web服务器的时候,服务器会给客户端发送一些信息,这些信息会保存在Cookie中,当浏览器再次访问服务器的时候,会在请求头中将Cookie的信息发送到服务器中,
- 服务器在向客户端发送Cookie的时候,在Http的响应字段添加:set-cookie: user=is; path=/;(属性之间必须添加空格和分号)。
cookie API
- public Cookie(String name,String vlaue) : name一经确定不能更改,value的值可以更改
- String getName() : 得到Cookie的名称
- Void setValue(String new Value) : 为Cookie设置一个新值
- String getValue(): 得到Cookie的值
- void setMaxAge( int expiry) :cookie在浏览器上到期的时间
- int getMaxAge() :
- void setPath(String url): 设置Cookie的有效目录
- String getPath(): 得到Cookie的有效目录
- void setDomain(String pattern): 设置Cookie的有效域
- String getDomain(): 返回该Cookie的有效域
- void setVersion(int v): 设置cookie的版本
- int getVersion():
- void setComment(String purpose) 设置Cookie的注解部分
- String getComment():
- void setSecure(boolean flag): 设置时候使用安全的协议传送
public class MyCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
String lastAccessTime = null;
Cookie[] cookies = req.getCookies();
for(int i = 0;i < cookies.length;i++){
if("lastAccess".equals(cookies[i].getName())){
lastAccessTime = cookies[i].getValue();
break;
}
}
/*=是赋值运算符,==是关系运算符; ===是全等运算符。*/
if (lastAccessTime ==null){
resp.getWriter().println("第一次访问该网站");
} else {
resp.getWriter().println("您的上次的访问时间是" + lastAccessTime );
}
String format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
Cookie cookie = new Cookie("lastAccess",format);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
Session
- 将会话数据保存到服务端的技术
- 过程
- 浏览器访问Web服务器的时候,Servlet容器就会创建一个Session对象和ID属性,其中Session对象中保存相关数据,ID相当于标识号,当客户端再次访问浏览器的时候,只要将标识号传递给服务器,服务器就可以根据ID拿到相对的Session对象来给它服务。
- 其中:ID的传递是靠Cookie传递的。
HttpSessionApi
- 重载
- public HttpSession getSession(boolean create)
- public HttpSession getSession();
- 方法
- String getId()
- long getCreationTime()
- long getLastAccessedTime()
- void setMaxinactiveInterval(int interval) 修改当前会话的默认超时时间间隔
- boolean isNew()
- void invaliddate()
- ServletContext getServletContext() 返回当前HttpSession对象代表的Web应用程序对象
- void setAttribute(String name;Object value)
- String getAttribute()
- void removeAttribute(String name)
Session 超时管理
- 因为Http协议中,Web服务器不能判断客户浏览器是否还在继续访问,所以设置指定时间让他关闭。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
简单购物
public class Book implements Serializable {
//定义程序序列化ID。为了验证版本一致性
private static final long serialVersionUID = 1L;
private String id;
private String name;
public Book() {
}
public Book(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
* 数据库模拟类
* */
public class BookDB {
private static final long serialVersionUID = 1L;
private static Map<String ,Book> books = new LinkedHashMap<String ,Book>();
static {
books.put("1",new Book("1","JAVA"));
books.put("2",new Book("2","jdbc"));
books.put("3",new Book("3","spring"));
books.put("4",new Book("4","spring cloud"));
books.put("5",new Book("5","spring mvc"));
}
public static Collection<Book> getAll(){
return books.values();
}
public static Book getBook(String id){
return books.get(id);
}
}
public class ListBookServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html/charset=utf-8");
PrintWriter writer = resp.getWriter();
Collection<Book> books = BookDB.getAll();
writer.println("本站提供的图书有:<br />");
for (Book book : books) {
String url = "/chatper05/PurchaseServlet?id=" + book.getId();
writer.println(book.getName() + "<a href='" + url + "' >点击购买<br />");
}
}
}
public class CartServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
// 变量cart引用用户的购物车
List<Book> cart = null;
//变量pruFlag标记用户是否购买过该商品
boolean purFlay = true;
//获得用户的session
HttpSession session = req.getSession(false);
//判断
if (session ==null ){
purFlay = false;
}else {
//获得用户购物车
cart = (List<Book>) session.getAttribute("cart");
//如果购物车为空,则purFlag使flase
if (cart ==null){
purFlay = false;
}
}
if(!purFlay){
writer.println("您还没有购买任何东西");
}else {
writer.println("您购买的图书有:");
double price = 0;
for (Book book : cart) {
writer.println(book.getName() +"<br />");
}
}
}
}
- 如果浏览器对cookie功能进行了禁用,拿不到Sesion对象,就需要使用URL实现Session跟踪
- encodeURL(String url); 对于超链接中和form表单action中url进行重写
- encodeRedirectURL(String url): 对传递到sendRedirect()中的URL进行重写
- 进行重写后session的标识号就会出现在请求地址中
简单登录
package com.login;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.login;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
PrintWriter writer = resp.getWriter();
if ("chen".equals(username) && "123".equals(password)){
User user = new User();
user.setUsername(username);
user.setPassword(password);
req.getSession().setAttribute("user",user);
resp.sendRedirect("/chapter05/IndexServlet");
}else {
writer.println("用户名和密码错误,登录失败");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
package com.login;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
PrintWriter respWriter = resp.getWriter();
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
HttpSession session = req.getSession();
User user = (User) session.getAttribute("user");
if(user == null){
respWriter.println("您还没有登录,请<a href='/chapter05/Login.html'>登录</a>'");
}else {
respWriter.println("您已登录,欢迎您:" + user.getUsername() +"!");
respWriter.println("<a href='/chapter05/LogoutServlet'></a>");
//创建Cookie存储Session的标识号
Cookie jsessionid = new Cookie("JSESSIONID", session.getId());
jsessionid.setMaxAge(60 * 30);
jsessionid.setPath("/chapter05");
resp.addCookie(jsessionid);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.login;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
//将Session中User对象移除
req.getSession().removeAttribute("user");
resp.sendRedirect("/chapter05/IndexServlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form name="reg" action="/chapter05/LoginServlet" method="post"><br>
用户名: <input type="text" name="username">
密码: <input type="password" name="password">
<input type="submit" value="登录" id="bt">
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<servlet>
<servlet-name>IndexServlet</servlet-name>
<servlet-class>com.login.IndexServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>IndexServlet</servlet-name>
<url-pattern>/IndexServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.login.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.login.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/LogoutServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>CheckServlet</servlet-name>
<servlet-class>com.login.CheckServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CheckServlet</servlet-name>
<url-pattern>/CheckServlet</url-pattern>
</servlet-mapping>
</web-app>
复杂登录(加了验证码)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form name="reg" action="/chapter05/LoginServlet" method="post"><br>
用户名: <input type="text" name="username"><br/>
密码: <input type="password" name="password"><br/>
验证码:<input type="text" name="check_code"><br/>
<img src="/chapter05/CheckServlet">
<br/>
<input type="submit" value="登录" id="bt">
</form>
</body>
</html>
package com.login;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class CheckServlet extends HttpServlet {
private static int WIDTH = 60;//验证码图片宽度
private static int HEIGHT = 20;//验证码图片高度
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
resp.setContentType("image/jpeg");
ServletOutputStream sos = resp.getOutputStream();
//设置浏览器不缓存图片
resp.setHeader("Pragma","No-cache");
resp.setHeader("Cache-Control","no-cache");
resp.setDateHeader("Expires",0);
//创建内存图像并获得图形上下文
BufferedImage bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics graphics = bufferedImage.getGraphics();
//产生随机认证码
char [] rands = generateCheckCode();
//产生图像
drawBackground(graphics);
drawRands(graphics,rands);
//结束图像的绘制过程,完成图像
graphics.dispose();
//将图像输出到客户端
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(bufferedImage,"JPEG",bos);
byte[] buf = bos.toByteArray();
resp.setContentLength(buf.length);
sos.write(buf);
bos.close();
sos.close();
//将当前验证码反倒Session
session.setAttribute("check_code",new String(rands));
//下面代码有错,Session对象必须在提交响应前获得
//req.getSession().setAttribute("check_code",new String(rands));
}
private void drawRands(Graphics graphics, char[] rands) {
graphics.setColor(Color.BLACK);
graphics.setFont(new Font(null,Font.ITALIC|Font.BOLD,18));
//在不同的高度输出验证码的每个字符
graphics.drawString("" + rands[0],1,17);
graphics.drawString("" + rands[1],16,15);
graphics.drawString("" + rands[2],31,18);
graphics.drawString("" + rands[3],46,15);
System.out.println(rands);
}
private void drawBackground(Graphics graphics) {
//画背景
graphics.setColor(new Color(0xDCDCDC));
graphics.fillRect(0,0,WIDTH,HEIGHT);
//产生120个干扰点
for(int i=0;i<120;i++){
int x = (int) (Math.random() * WIDTH);
int y = (int) (Math.random() * HEIGHT);
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
graphics.setColor(new Color(red,green,blue));
graphics.drawOval(x,y,1,0);
}
}
//生成一个4字符的验证码
private char[] generateCheckCode() {
//定义验证码的字符表
String chars = "0123456789abcdefghijklmnopqrstuvwxyz";
char[] rands = new char[4];
for(int i=0;i<4;i++){
//返回36之内的所有整数
int rand = (int) (Math.random() * 36);
//返回指定索引处的值
rands[i] = chars.charAt(rand);
}
return rands;
}
}
package com.login;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String check_code = req.getParameter("check_code");
String code = (String) req.getSession().getAttribute("check_code");
PrintWriter writer = resp.getWriter();
if ("chen".equals(username) && "123".equals(password) && check_code.equals(code)){
User user = new User();
user.setUsername(username);
user.setPassword(password);
req.getSession().setAttribute("user",user);
resp.sendRedirect("/chapter05/IndexServlet");
}else {
writer.println("用户名和密码错误,登录失败");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}