• java_第一年_JavaWeb(6)


    会话

    会话:浏览器从打开一个进程访问服务器到该浏览器关闭,我们称之为一个会话;

    在浏览器和服务器交互期间,会不可避免地产生一些数据,而为了为每个用户保存其对应的数据,可使用两种技术:Cookie和Session;

    Cookie

    客户端技术,服务器会把用户的数据以cookie的形式写给每个客户端,当其再次访问时,就会携带相关的数据,这样使得服务器可以区分客户端处理数据;

    Cookie在java中是通过javax.servlet.http.Cookie类创建的;其提供的方法有:

    Cookie(String name , String value);//实例化Cookie对象,传入其名称和值
    public String getNme();//取得Cookie的名称
    public String getValue();//取得Cookie的值
    public void setValue(String newValue);//设置Cookie的值
    public void setMaxAge(int expiry);//设置Cookie最大的保存时间
    public int getMaxAge();//获取Cookies的有效期,单位是秒
    public void setPath(String uri);//设置cookie的有效路径,即在访问哪些路径时是自带Cookie的
    public String getPath();//获取cookie的有效路径
    public void setDomain(String pattern);//设置cookie的有效域
    public String getDomain();//获取cookie的有效域

    运用Cookie为每个浏览器都设置一个Cookie,并检查该请求是否已携带cookie:

    import javax.servlet.http.Cookie;
    PrintWriter out = resppnse.getWriter();
    Cookie[] cookies = request.getCookies();
    if (cookies != null){
        for (int i = 0,i<cookies.length,i++){
            Cookie cookie = cookies[i];
    //找到所要核对的cooki名
            if (cookie.getName().equals("lastaccesstime")){
                Long  lastaccesstime = Long.parseLong(cookie.getValue());
                Date date = new Date(lastaccesstime);
                out.write(date.toLocaleString());//将之前的cookie值转换为日期格式并输出
                }
            }
        }else{
            out.write("第一次访问本站");
        }
    Cookie cookie = new Cookie ("lastacccesstime",System.currentTimeMillis()+"");//无论是否第一次访问都为cookie设置当前的时间值
    response.addCookie(cookie);//将新的cookie添加到response中并输出到客户端    

    一个Cookie只能标识一种信息,即一个web站点可以给同一个浏览器发送多个站点,一个浏览器也可以储存不同站点的Cookie标识;

    如果不使用getMaxAge()将cookie保存到硬盘中的话,其信息是储存在内存中的,即关闭浏览器下次再登录是找不到原来的Cookie信息;删除Cookie时将其时间设置为0即相当于删除;

    存储中文时需要使用URLEncoder类中的encode(String s,String enc)方法进行中文转码;

    Cookie cookie = new Cookie("name",URLEncoder.encode("小兆","UTF-8"));

    获取cookie中文时也需用URLEncoder类中的decode(String s ,String enc)进行解码;

    URLDecoder.decode(cookies[i].getValue(),"UTF-8");

    Session

    服务器为每个用户浏览器都创建一个Session对象,用于保存用户数据,当用户去访问服务器其他程序时,其他程序可以通过用户的Session取出该用户的数据,为用户服务;

    与Cookie的区别主要是:Cookie是写给浏览器,而Session是存在于服务器,当需要调用时,通过request对象的getSession方法得到Session对象;

    getSession()方法会自动判断是否已存在session,如有,则调用,如没有,则创建;且一个session会有一个自己的ID以cookie的形式发送给浏览器,所以getSession()方法中应该存在创建sessionID且将其传给Cookie对象的程序过程;

    判断是否已存在session:

    HttpSession session = request.getSession();
    session.setAttribute("data","小兆");//记得前面需将字符编码改为"UTF-8"
    String sessionID= session.getID();
    if(session.isNew()){
        response.getWriter().print("创建成功,其session的id是:"+sessionID);
    }else{
         response.getWriter().print("已存在session,其session的id是:"+sessionID);
         }

    session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间;

    <session-config>
            <session-timeout>12</session-tiomeout>
    </session-config>

    防止表单进行多次提交

    在客户端防止:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>Form表单</title>
            <script type="text/javascript">
            var isCommitted = false;//表单是否已经提交标识,默认为false
            function dosubmit(){
                if(isCommitted==false){
                    isCommitted = true;//提交表单后,将表单是否已经提交标识设置为true
                    return true;//返回true让表单正常提交
                }else{
                    return false;//返回false那么表单将不提交
                }
            }
        </script>
      </head>
      
      <body>
          <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" onsubmit="return dosubmit()" method="post">
            用户名:<input type="text" name="username">
            <input type="submit" value="提交" id="submit">
        </form>
      </body>
    </html>

    可以通过运用JavaScript本身对其提交进行控制;

    在服务端防止,在服务器上生成一个唯一标识码,称为Token令牌;在用户的session中保存Token并将其送往Form表单中,而form表单使用隐藏

    域来储存Token,提交的时候一同提交到服务器中,此时服务器就根据session中的Token和提交上来的Token进行比较,如果一样,则提交成功,且在成功后将其Token信息在session中删除;如果发现表单或服务器中没携带Token或者其值不一致,则拒绝其表单提交;

     生成唯一标识码并存储在session中,随后跳转到xxx.jsp页面:

    String token = TokenProccessor.getInstance().makeToken();//创建令牌
    request.getSession().setAttribute("token", token);  //在服务器使用session保存token(令牌)
    request.getRequestDispatcher("/xxx.jsp").forward(request, response);//跳转到form.jsp页面

    编辑xxx.jsp页面,设置from表单,使用隐藏域来储存Token:

    <form action="${pageContext.request.contextPath}/xxx" method="post">
        <input type="hidden" name="token" value="${token}"/>
        用户名:<input type="text" name="username"> 
        <input type="submit" value="提交">
    </form>

    对比表单提交上来的以及服务器session对象储存的Token的值,判断是否处理请求:

    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class DoFormServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
    
                boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
                if(b==true){
                    System.out.println("请不要重复提交");
                    return;
                }
                request.getSession().removeAttribute("token");//移除session中的token
                System.out.println("处理用户提交请求!!");
            }
            
            /**
             * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
             * @param request
             * @return 
             *         true 用户重复提交了表单 
             *         false 用户没有重复提交表单
             */
            private boolean isRepeatSubmit(HttpServletRequest request) {
                String client_token = request.getParameter("token");
                //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
                if(client_token==null){
                    return true;
                }
                //取出存储在Session中的token
                String server_token = (String) request.getSession().getAttribute("token");
                //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
                if(server_token==null){
                    return true;
                }
                //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
                if(!client_token.equals(server_token)){
                    return true;
                }
                
                return false;
            }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    
    }

    关于前面的创建令牌方法大家可以自己实现即可,保证其唯一性;

  • 相关阅读:
    WEBSERVICE 分析器错误信息: 未能创建类型
    Powerdesigner中表导出sql语句关于字段注释乱码的问题
    配置redis服务器允许远程连接
    [转]ubuntu系统重新分区、根目录扩容
    [转]自动驾驶平台Apollo 2.5环境搭建
    [转]在ROS下使用zeroconf配置多机通信
    ROS 安装完成后运行小乌龟示例程序
    [转]RoboWare Studio的使用和发布器/订阅器的编写与测试
    【转】ROS之topic和service通信比较
    【转】贝叶斯公式的直观理解(先验概率/后验概率)
  • 原文地址:https://www.cnblogs.com/lzj-learn/p/11613702.html
Copyright © 2020-2023  润新知