JavaWeb的会话管理(cookie & session)&拦截器/过滤器

会话技术

javaWeb中会话是,客户端和服务器之间的一次交互。

打开浏览器,一顿操作后,最后关闭浏览器,就是一个会话。

会话跟踪,用户的数据单独独立的跟随用户的足迹。

有两种方法:浏览器端的cookie 服务器端的 Session会话技术。

Cookie会话技术

把客户的数据放到浏览器端,用来存储一小段数据的。

创建cookie

创建Cookie 唯一的创建方法

  • Cookie cookie = new Cookie(String key,String value);

  • 创建cookei的构造方法只有一个构造方法

  • 参数都是String类型


    • 默认创建的Cookei,到期时间是保存至浏览器关闭
    • 保存的路径是当前项目下的路径

    通过方法设置

    • 保存时间
    // 设置时间   0销毁 -1 保存到浏览器关闭
    cookie.setMaxAge(0);
    
    • 保存路径
    // 设置路径
            cookie.setPath("/hui");
    

获得Cookei

获得的cookei的只能是获得使用,所以是个数组

// 没有获得单个cookei的方法,直接获得所有的cookie
     Cookie [] cookies = request.getCookies();
     for (int i = 0; cookies!=null && i < cookies.length; i++) {
         Cookie cookie = cookies[i];

         // 获得
         String name = cookie.getName();
         System.out.println("name="+name);

         String value = cookie.getValue();
         System.out.println("value="+value);

         int maxAge = cookie.getMaxAge();
         System.out.println(maxAge);

         String path = cookie.getPath();
         System.out.println(path);

cookei保存中文问题

1.cookie的key不能设置为中文

2.value中文会乱码


cookie 存储中文时如果乱码可以使用

URLEncoder编码,URLDecoder解码

存储编码 :String name URLEncoder.ecoder(“张三”)

取出解码: URLDecoder.decode(name) = 张三

响应给浏览器

resp.addCookie(cookie);

1)Cookie:将数据保存在浏览器客户端的技术

服务器把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了

2)Session:将数据保存在服务端的技术

服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务

Cookie 原理

在这里插入图片描述

1)服务端创建cookie对象

2)发送cookie信息到浏览器(HttpServletResponse 中提供void addCookie(Cookie cookie)方法)

例如,响应头中增加 Set-Cookie: name=zhangsan

3)浏览器将得到的cookie信息保存在浏览器端

4)通过浏览器下次访问web应用时,请求数据中会带上cookie信息例如,请求头中 Cookie: name=zhangsan

5)服务器端收到浏览器发送的cookie信息

常用的方法

方法
Cookie(String name, String value)创建cookie对象的构造方法,value是字符串类型,tomcat8后value可以使用中文
String getName()取得Cookie的名字
String getValue()取得Cookie的值
void setValue(String newValue)设置Cookie的值
void setMaxAge(int expiry)设置Cookie的最大保存时间,单位秒,即cookie的有效期,默认会话结束,cookie失效。值为 0 时,表示删除该 Cookie
int getMaxAge()获取Cookies的有效期
void setPath(String uri)设置cookie的有效路径,比如把cookie的有效路径设置为"/aaa",那么浏览器访问"aaa"的web资源时,就会带上cookie
String getPath()获取cookie的有效路径

获取Cokie

//获取所有的Cookie
Cookie[] cks=request.getCookies();
//遍历Cookie
for(Cookie ck:cks){
 //检索出自己的Cookie
 if(ck.getName().equals("code"))
 {
     //记录Cookie的值
     code=ck.getValue();
     break;
 }
}

修改Cookie

只需要保证Cookie的名和路径一致即可修改

//修改Cookie
Cookie ck=new Cookie("code", code);
ck.setPath("/");
ck.setMaxAge(-1);
response.addCookie(ck);//让浏览器添加Cookie

注意:如果改变cookie的name和有效路径会创建cookie而改变cookie值,有效期会覆盖原有cookie

Cookie编码与解码

Cookie默认不支持中文,只能包含ASCII字符,所以Cookie需要对Unicode字符进行编码,否则会出现乱码。

  • 编码可以使用java.net.URLEncoder类的encode(String str,String encoding)方法
  • 解码使用java.net.URLDecoder类的decode(String str,String encoding)方法

创建带中文Cookie

// 使用中文的 Cookie. name 与 value 都使用 UTF-8 编码. 
Cookie cookie = new Cookie(URLEncoder.encode("姓名", "UTF-8"), URLEncoder.encode("二狗子", "UTF-8"));
// 发送到客户端   
response.addCookie(cookie);

Cookie优点和缺点

优点

  • 可配置到期规则。
  • 简单性:Cookie 是一种基于文本的轻量结构,包含简单的键值对。
  • 数据持久性:Cookie默认在过期之前是可以一直存在客户端浏览器上的。

缺点

  • 大小受到限制:大多数浏览器对 Cookie 的大小有 4K、8K字节的限制。
  • 用户配置为禁用:有些用户禁用了浏览器或客户端设备接收 Cookie 的能力,因此限制了这一功能。
  • 潜在的安全风险:Cookie 可能会被篡改。会对安全性造成潜在风险或者导致依赖于Cookie 的应用程序失败。

Session对象

Session概述

  • Session用于记录用户的状态。Session指的是在一段时间内,单个客户端与Web服务器的一连串相关的交互过程。
  • 在一个Session中,客户可能会多次请求访问同一个资源,也有可能请求访问各种不同的服务器资源。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-icT39I08-1680667313526)(D:\前锋学习笔记\笔记\image-20230405014848837.png)]

Session原理

  • 服务器会为每一次会话分配一个Session对象
  • 同一个浏览器发起的多次请求,同属于一次会话(Session)
  • 首次使用到Session时,服务器会自动创建Session,并创建Cookie存储SessionId发送回客户端
@WebServlet(name = "session1", value = "/s1")
public class session1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建session
        // 如果没有,其实就请求cookie中没有JSESSIONId
        // 就会创建session
        HttpSession session = request.getSession();
        System.out.println("sessionid="+session.getId());
    }
}

注意:session是由服务端创建的

Session使用

Session作用域:拥有存储数据的空间,作用范围是一次会话有效

  • 一次会话是使用同一浏览器发送的多次请求。一旦浏览器关闭,则结束会话
  • 可以将数据存入Session中,在一次会话的任意位置进行获取
  • 可传递任何数据(基本数据类型、对象、集合、数组)

获取Session

session是服务器端自动创建的,通过request对象获取

//获取Session对象 
HttpSession session=request.getSession();
System.out.println("Id:"+session.getId());//唯一标记,

Session与Request应用区别

  • request是一次请求有效,请求改变,则request改变
  • session是一次会话有效,浏览器改变,则session改变

Session 域数据销毁

// 清除session数据
     session.removeAttribute("sessionid");
     // 销毁session
     session.invalidate();

拦截器/过滤器(filter)

拦截请求

开发步骤

  • 创建类
  • 实现Filter接口
  • 重写三个方法(init(),doFilterr,destroy())

案例:当用户登录后才可以访问其他的页面,不登录就无法访问其他的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/test" method="post">
  <input type="text" name="username"><br>
  <input type="password" name="password"><br>
  <input type="submit" value="登录">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>个人中心</title>
</head>
<body>
<h1>个人中心</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加用户</title>
</head>
<body>
<h1>用户添加</h1>
</body>
</html>
@WebServlet(name = "test", value = "/test")
public class test extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if ("admin".equals(username) && "123456".equals(password)){
            HttpSession session = request.getSession();
            session.setAttribute("user",username);
        }else {
            response.sendRedirect(request.getContextPath()+"/index.html");
        }
     }
}

拦截器

/**
 * @author 二手Java程序员
 * @since 2023/4/5 2:38
 */
@WebFilter("/*")
public class Login implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request; // 类型不同需要强制转一下
        HttpServletResponse resp = (HttpServletResponse) response; // 类型不同需要强制转一下
        String requestURL = req.getRequestURI();  // 获取请求中返回的路径
        System.out.println("requsetURL="+requestURL);
        if (requestURL.contains("info") || requestURL.contains("add")){ // 判断是请求谁的什么路径
            HttpSession session = req.getSession();
            Object user = session.getAttribute("user"); // 获取对象
            if (user == null){ // 如果对象为空就跳重定向到登录界面
                resp.sendRedirect(req.getContextPath()+"/index.html");
            }

        }
        chain.doFilter(request,response);

    }

    @Override
    public void destroy() {
        System.out.println("销毁");
    }


}

案例二

需求:做登录认证

目前,服务器中有管操作的几个Sevlet

  • UserLoginServlet --> /login
  • UserAddServlet --> /add
  • UserDeleteSerlet --> /delete

这些Servlet 有对呀的映射路径,要保证只有登录后才可以进行注册删除

实现思路:

  • 执行登录时,如果登录成功,将登录信息放入session
  • 在真正执行注册删除等功能前,先判断有没有登录
  • 其实就是判断session中有没有登录的信息

login

@author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/login")
public class UserLoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        if ("admin".equals(username)){
            HttpSession session = req.getSession();
            session.setAttribute("username",username);
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败用户名或密码错误");
        }

    }
}

add

/**
 * @author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/add")
public class UserAddServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 先判断有没有登录
        HttpSession session = req.getSession();
        Object username = session.getAttribute("username");
        if (username != null){
            System.out.println("登录成功。。添加用户");
        }else {
            System.out.println("没有登录,没有操作权限");
        }
    }
}

delete

/**
 * @author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/delete")
public class UserDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 先判断有没有登录
        HttpSession session = req.getSession();
        Object username = session.getAttribute("username");
        if (username != null){
            System.out.println("登录成功。。执行删除操作");
        }else {
            System.out.println("没有登录,没有操作权限");
        }
    }
}

lgout 退出

/**
 * @author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/logout")
public class UserLgoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 先判断有没有登录
        HttpSession session = req.getSession();
        session.invalidate();
        System.out.println("退出登录,销毁session");
    }
}

使用拦截器、过滤器改造

场景:服务器中有很多处理请求的servlet,项目要求登录认证所以我们每个Servlet执行功能前要对登录信息判断,就会有很多次登录判断的代码编写,重复性能很高!


因为以上操作不高效,代码重复率太高!解决方法就是使用拦截器。

登录

/**![请添加图片描述](https://img-blog.csdnimg.cn/9f195dbbfb4a4f5d861ef388e36fe160.png)

 * @author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/login")
public class UserLoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("登录成功");
    }
}

添加

/**
 * @author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/add")
public class UserAddServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("添加用户");
    }
}

删除

/**
 * @author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/delete")
public class UserDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("执行删除操作");
    }
}

拦截器

/**
 * @author 二手Java程序员
 * @since 2023/4/5 11:48
 */
@WebFilter("/login")
public class UserLoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String uri = req.getRequestURI();
        if (uri.contains("/login")){
            chain.doFilter(request,response);
            return;
        }
        HttpSession session = req.getSession();
        Object username = session.getAttribute("username");
        if (username != null) { // 不为空就说明已经登录了
            chain.doFilter(request,response);
            return;
        }else {
            System.out.println("没有登录,不能操作");
            // 可以跳转页面
        }
    }

    @Override
    public void destroy() {

    }
}

退出销毁session

/**
 * @author 二手Java程序员
 * @since 2023/4/5 11:14
 */
@WebServlet("/logout")
public class UserLogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 先判断有没有登录
        HttpSession session = req.getSession();
        session.invalidate();
        System.out.println("退出登录,销毁session");
    }
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二手Java程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值