1. 程式人生 > >Session學習---Session池、驗證碼

Session學習---Session池、驗證碼

本篇部落格知識點

1.演示request、session、application(ServletContext)的生命週期
2.Session池的工作原理
3.網頁驗證碼

演示request、session、application(ServletContext)的生命週期
主要思路: 在SaveServlet中 設定三個容器的name屬性,分別賦值。再寫個超連結個GetServlet中去讀取出來,輸出到頁面。

在IE中存、在IE中拿(瀏覽器未關閉) session 和application拿到了
這裡寫圖片描述

在IE中存。在360瀏覽器中拿 只拿到了application
這裡寫圖片描述

總結:
request 生命週期是一次請求,一個request。所以Getsevlet和SaveSevlet 中是兩個request 因此拿不到
session 生命週期和瀏覽器是一起的,瀏覽器不關閉,同一個瀏覽器上拿到的session是同一個 因此IE在IE上拿的到 360瀏覽器拿不到IE存的session
application 生命週期是和伺服器一起的 伺服器一直未關閉,所以不管什麼瀏覽器都能拿到applicatton容器內的值

SavaServlet.java

package cn.hncu.servlets2;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse
; import javax.servlet.http.HttpSession; public class SaveServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType
("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); // 通過三個容器request、session、application 分別設定三個屬性 看看能在哪兒拿到 推出他們的生命週期 String name = "胡龍華"; request.setAttribute("name", name+"_request"); HttpSession session = request.getSession(); session.setAttribute("name", name+"_session"); ServletContext application = getServletContext(); application.setAttribute("name", name+"_application"); out.println(" <a href='GetServlet'>檢視三個容器屬性</a><br/>"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); } }

GetServlet.java

package cn.hncu.servlets2;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GetServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
        out.println("  <BODY>");

        String requestName = (String) request.getAttribute("name");
        out.println("requestName:"+requestName+"<br/>");

        String sessionName = (String) request.getSession().getAttribute("name");
        out.println("sessionName:"+sessionName+"<br/>");

        String applicationName = (String) getServletContext().getAttribute("name");
        out.println("applicationName:"+applicationName);
        out.println("  </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();
    }

}

Session池工作原理

當瀏覽器訪問伺服器時,伺服器會去讀取瀏覽器中的一個cookie ,這個cookie的name 為 JESSIONID 拿到他的value值,SESSIONID 去Session池匹配,找到了建立連線,未找到就重新建立一個SESSIONID並且寫到cookie裡
這裡寫圖片描述

通過不斷維護這個seesion池,完成回話。session池的底層原理是HashMap();

有的瀏覽器禁用了cookie,那麼按照這種方式就沒辦法建立會話連線,因此為了相容,可以值禁用cookie時,通過位址列把JESSIONID發給伺服器格式如下:

正是因為這種相容方式,容易系統容易被人黑。使用者退出後Session預設的時間是30分鐘,因此要讓使用者安全退出—在Session池中去掉哪條記錄

        //安全退出
        HttpSession s = request.getSession();
        s.invalidate(); //讓session失敗
        out.println("您已經安全退出!");

另外一種情況是:使用者不小心關閉了瀏覽器,想要重新開啟恢復剛剛的頁面資訊(恢復剛剛session通話),如何做? — 伺服器像使用者寫一個普通cookie 把剛剛的SESSIONID放過去就好了

//本來,瀏覽器關閉之後重啟,上一次的使用者臨時資訊是訪問不了的
        //把cookie和session技術聯合起來,實現讓使用者不小心關閉瀏覽器,使用者的臨時資訊還能在5分鐘之內重啟瀏覽器有效
        //我們在伺服器端寫程式碼手動建立一個 JSESSIONID=....的普通cookie,發向客戶端
        String id = request.getSession().getId();//拿到該使用者的session id
        Cookie c = new Cookie("JSESSIONID",id);
        c.setMaxAge(60*5);//5分鐘
        c.setPath(request.getContextPath());
        response.addCookie(c);

網頁驗證碼

邏輯示意圖: 每個使用者都在請求驗證碼,因此必須放在Session中!!!!
這裡寫圖片描述

CodeImgServlet.java程式碼 生成驗證碼

package cn.hncu.servlet2;


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CodeImgServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        //☆1☆--相比純java方式有變化的地方
        resp.setContentType("image/jpeg");//設定http響應頭---告訴瀏覽器我現在發的是這個圖片格式的資料,你用相應的方式來解析

        //定義圖片的寬和高
        int w=60;
        int h=30;

        //宣告一個RGB格式的記憶體中的圖片
        BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics g = img.getGraphics();

        //把背景變白色
        g.setColor(Color.white);
        g.fillRect(0, 0, w, h);
        //設定字型
        g.setFont(new Font("aa",Font.BOLD,18));

        //產生並draw出4個隨機數字
        Random r = new Random();
        String sCode="";
        for(int i=0;i<4;i++){
            int a = r.nextInt(10);//生成0~9之間的隨機整數
            int y = 15+r.nextInt(20);//產生隨機的垂直位置
            //產生隨機顏色
            Color c = new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256));
            g.setColor(c);

            g.drawString(""+a, i*15, y);
            sCode +=a; //生成真正的驗證碼
        }
        req.getSession().setAttribute("sCode", sCode);//把驗證碼標準答案存入session容器

        //畫幾條幹擾線
        for(int i=0;i<10;i++){
            //產生隨機顏色
            Color c = new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256));
            g.setColor(c);
            g.drawLine(r.nextInt(60), r.nextInt(30), r.nextInt(60), r.nextInt(30));
        }

        g.dispose();//類似於IO中的flush(),把圖形資料刷到img中
        //把記憶體圖片img物件儲存到一個jpg檔案
        ImageIO.write(img, "JPEG", resp.getOutputStream() );//☆2☆

    }
}

LoginServlet.java

package cn.hncu.servlet2;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
        out.println("  <BODY>");

        //獲取使用者上傳引數中的驗證碼--待測資料
        String code = request.getParameter("code");

        //獲取session中驗證碼的標準答案
        HttpSession session =  request.getSession();
        String sCode = (String)session.getAttribute("sCode");
        session.removeAttribute("sCode");//驗證碼用過一次就要讓它失效,無論這次是否成功

        //判斷驗證碼是否正確
        if(sCode==null || !sCode.equals(code)){
            out.println("驗證碼輸入錯誤!");
        }else{//驗證碼正確
            //把使用者名稱和密碼提交給後臺資料庫去校驗----這裡簡單模擬一下
            String nm = request.getParameter("name");
            String pwd = request.getParameter("pwd");
            if(nm!=null && nm.trim().equals(pwd)){//假設這樣算登入成功
                out.println("登入成功!");
            }else{
                out.println("登入失敗!");
            }
        }

        out.println("  </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();
    }

}

頁面和xml

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Cookie-Session技術演示</title>
  </head>

  <body>
    <h2>上一段Cookie技術演示</h2>

    <a href="CookieDemo1">Cookie技術演示1</a> <br/>

    <a href="servlet/CookieDemo2">該servlet用於演示Cookie的訪問許可權</a>
    <br/><br/>

    <a href="LoginServlet">利用Cookie技術顯示上次登入的時間</a>
    <br/><br/>

    <a href="TestCookieNumServlet">測試瀏覽器支援cookie的數量和長度</a>
    <br/><br/>


    <a href="jsps/show.jsp">案例:利用cookie記錄使用者最近訪問的圖片資訊</a>
    <br/><br/>

    <a href="jsps/cookie.jsp">前端頁面中用js來操作cookie技術演示</a>
    <br/><br/>

    <hr/>
    <h2>下一段演示Session技術</h2>
    <a href="jsps/contain.jsp"> request, session, application(ServletContext) 這三個容器生命週期對比演示</a>
    <br/>
    <a href="LogoutServlet">安全退出</a>

    <br/><br/>
    <script type="text/javascript">
         function changeImg(){
             var img = document.getElementById("codeImg");
             img.src="code?"+new Date().getTime();
         }
    </script>
    <h2>使用者註冊</h2>
     <form action="LoginServlet2" method="post">
            姓名:<input type="text" name="name"><br/>
            密碼:<input type="password" name="pwd"><br/>
            驗證碼:<input type="text" name="code"/><img id="codeImg" src="code"/><a href="javascript:changeImg();">看不清</a><br/>
          <input type="submit" value="註冊">
     </form>
  </body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>
  <servlet>
    <servlet-name>CookieDemo1</servlet-name>
    <servlet-class>cn.hncu.servlet.CookieDemo1</servlet-class>
  </servlet>

  <servlet>
    <servlet-name>CookieDemo2</servlet-name>
    <servlet-class>cn.hncu.servlet.CookieDemo2</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>cn.hncu.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>TestCookieNumServlet</servlet-name>
    <servlet-class>cn.hncu.servlet.TestCookieNumServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>cn.hncu.servlet.ShowServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>SaveServlet</servlet-name>
    <servlet-class>cn.hncu.servlet2.SaveServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>GetServlet</servlet-name>
    <servlet-class>cn.hncu.servlet2.GetServlet</servlet-class>
  </servlet>

  <servlet>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>cn.hncu.servlet2.LogoutServlet</servlet-class>
  </servlet>

  <servlet>
    <servlet-name>LoginServlet2</servlet-name>
    <servlet-class>cn.hncu.servlet2.LoginServlet</servlet-class>
  </servlet>

  <servlet>
    <servlet-name>CodeImgServlet</servlet-name>
    <servlet-class>cn.hncu.servlet2.CodeImgServlet</servlet-class>
  </servlet>





  <servlet-mapping>
    <servlet-name>CookieDemo1</servlet-name>
    <url-pattern>/CookieDemo1</url-pattern>
  </servlet-mapping>    
  <servlet-mapping>
    <servlet-name>CookieDemo2</servlet-name>
    <url-pattern>/servlet/CookieDemo2</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/LoginServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>TestCookieNumServlet</servlet-name>
    <url-pattern>/TestCookieNumServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ShowServlet</servlet-name>
    <url-pattern>/ShowServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>SaveServlet</servlet-name>
    <url-pattern>/SaveServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>GetServlet</servlet-name>
    <url-pattern>/GetServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>LogoutServlet</servlet-name>
    <url-pattern>/LogoutServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>LoginServlet2</servlet-name>
    <url-pattern>/LoginServlet2</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>CodeImgServlet</servlet-name>
    <url-pattern>/code</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

重寫URL技術:當流浪器禁用cookie時,正常的方式就無法建立session,重寫URL技術可以完美的解決這個問題。程式碼如下encodeURL

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Cookie-Session技術演示</title>
  </head>

  <body>
    <h2>request, session, application(ServletContext) 這三個容器生命週期對比演示</h2>
    <pre>
      request:代表一次請求,每次請求的容器是獨立的。
                          不同的請求之間是無法共享該容器中的資料的。
      session:代表一個使用者,通常是指同一個瀏覽器,
                         該瀏覽器中的多個請求甚至是多個頁面是共享同一個session容器的。
                         如果瀏覽器關閉再開啟,則是另一個session容器,無法共享到上一次的session。
      application:代表一個專案(我們平時理解的一個網站)。
                        不但是多個請求,甚至是多個使用者(瀏覽器)都是共享該容器。只要Tomcat不關閉,這個容器一直存在。
                         但如果Tomcat關閉(或專案停止執行)則該容器消亡。
    </pre>

    <!-- 重寫url技術: 
        解決瀏覽器禁用cookie,導致瀏覽器在發出請求時不傳送JSESSIONID這個特殊的cookie,
         從面出現伺服器不認識該session使用者,由此造成無法共享session中的資訊。
      ---每次請求都會被伺服器當成一個新使用者(session)。
       重寫url技術的本質是: 我們寫程式碼在請求url後面手動加字串: ";jsessionid=29E4A2378278DAE4"
     -->



    <!-- 往容器中放值 -->
    <!-- 非重寫url的方式,,,無法突破瀏覽器“禁用cookie”的情況
       <form action="<%=request.getContextPath()%>/SaveServlet" method="post">
     -->

     <!-- 重寫url的方式 ,,能突破瀏覽器“禁用cookie”的情況 -->
     <%
       String url = response.encodeURL( request.getContextPath()+"/SaveServlet" ); //重寫url,即在引數(url)後面手動新增";jsessionid=5D787A90163F222827456857608E243D"
       System.out.println("url:"+url);
    %>
    <form action="<%=url%>" method="post">
       Name:<input type="text" name="name" /><br/>
       <input type="submit"/>
    </form>

    <br/>
    <% 
         url= response.encodeURL( request.getContextPath()+"/GetServlet" ); //重寫url,即在引數(url)後面手動新增";jsessionid=5D787A90163F222827456857608E243D"
    %>
    <a href="<%=url%>">讀取容器中的值</a>


  </body>
</html>

相關推薦

Session學習---Session驗證

本篇部落格知識點 1.演示request、session、application(ServletContext)的生命週期 2.Session池的工作原理 3.網頁驗證碼 演示request、session、application(ServletCont

Springboot使用session容器存取短信驗證

lis col 結果 gin 請求 scrip void ssi 不知道 Springboot使用session容器存取短信驗證碼,(手抖挖了坑在@WebListener類聲明時候加了個abstract導致springboot掃描不到這個監聽器) 需求:為了給app做接口,

android session的使用(圖片驗證

功能:android端要實現圖片驗證碼功能。 1、方法一:本地實現圖片驗證 在本地實現圖片驗證碼:這種方式,是不與伺服器驗證的,驗證碼在android端生成,並且自已校驗。 2、方法二:接收伺服器驗證圖片,提交時伺服器校驗。 這種方法,我

Django學習系列之captcha 驗證插件

應用 自動 sta 前端 流程 bsp msg char erro 安裝部署 安裝captcha pip3.6 install django-simple-captcha==0.4.6 settings.py中引入captcha INSTALLED_APPS = [

8 ELJSTLMVC購物車驗證

dispatch test war msg 存在 .get 生成隨機數 框架 輸入驗證碼 1.EL表達式 目的:從作用域中取出共享數據 ${p.屬性名稱} 使用EL獲取當前應用的上下文路徑 ${pageContext.getRequest().get

python 小數據塊詳解

得到 pyc 長度 超過 新的 小寫 bsp div 開始   首先我們來看看下面的問題,第一次遇到還以為見鬼了。 看到上面這麽多種情況剛開始直接就懵逼了。100ID一樣,1000就不一樣。終端運行情況居然會和pycharm不一

python--random模組(產生隨機值)洗牌驗證應用

前言: 在python中用於生成隨機數的模組是random,在使用前需要import random.random():生成一個0-1之間的隨機浮點數. random.uniform(a, b):生成[a,b]之間的浮點數. random.randi

DAY87-BBS專案(一) 資料庫設計與簡單登陸驗證

一、BBS專案之專案分析 專案流程: 1 搞清楚需求(產品經理) (1) 基於使用者認證元件和Ajax實現登入驗證(圖片驗證碼) (2) 基於forms元件和Ajax實現註冊功能 (3) 設計系統首頁(文章列表渲染) (4) 設計個人站點頁面---跨表查詢,分組查詢 (5)

Android 密碼輸入框驗證輸入框,完整版;

接上篇,優化了一下程式碼,新增一些屬性;       "space" //每個輸入框之間的間距;        "strokeWidth" //邊框的高度;        "checke

tensorflow基礎學習:字元數字驗證寫入tfrecord檔案封裝成類

今天分享一下我寫的一個小小程式,基本可以滿足數字+字元型別字串寫入tfrecord檔案。還請多多指教! 簡單說明:這個是數字+字元4位驗證碼的tfrecord生成程式碼,5位,6位的可以自行修改一下,也就一點程式碼。我因為有點晚了就先不改了,大家加油啦。 先做些準備工作。

34驗證

學習目標: 1、瞭解驗證碼的作用 2、掌握驗證碼的實現 學習過程: 一、為什麼需要驗證碼 1、什麼是驗證碼 相信大家經常上網都會見到驗證碼的,如下圖: 你可以隨便開啟一個有驗證碼的網站看看,那到底什麼是驗證碼呢?驗證碼上面的數字或者字母是隨機生成的,驗證其實就是一副

python基礎之小數據編碼

文本 讓其 http 數據池 浪費 技術 ket 文字 soft 一、代碼塊。if True:   print(333)   print(666) while 1:   a = 1   b = 2   print(a+b) for

Java 處理中文名稱檔案下載的處理驗證生成

建立DownLoadServlet,備份使用 import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; im

2018最新版 手機號驗證正則表示式 jq + 小程式

HTML: <!-- 表單 --> <input class="weui-input" id="tel" type="tel" placeholder="請輸入手機號"> <input class="weui-input" t

爬蟲之代理亂碼驗證

代理 爬蟲中為什麼需要使用代理 一些網站會有相應的反爬蟲措施,例如很多網站會檢測某一段時間某個IP的訪問次數,如果訪問頻率太快以至於看起來不像正常訪客,它可能就會會禁止這個IP的訪問。所以我們需要設定一些代理IP,每隔一段時間換一個代理IP,就算IP被禁止,依然可以換個IP繼續爬取。 代理的分

JAVAWEB開發之HttpServletResponse和HttpServletRequest詳解(上)(各種亂碼驗證重定向和轉發)

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 禁止瀏覽器快取 驗證碼圖片 // response.setH

SpringMVC登入註冊驗證

想要實現以下效果:首先jsp前臺頁面<body style="margin:150px 0 0 600px"> <!-- Panel面板 data-options 英文為:屬性 iconCls : string 設定一個16x16圖示的CSS類ID顯

爬蟲代理設定--爬取ip驗證ip是否可用驗證代理ip是否能用

昨天在爬取大眾點評的時候,剛開始還好好的,但一會就把我的ip給封啦,所以我就想給自己弄一個ip池,這樣我就可以繼續爬啦。網上找了一堆程式碼,發現好多都是python2的,它們請求使用urllib2的庫,這個庫在python3中合併成urllib,所以很多方法呼叫都出現錯誤,所

Tornado---cookiecsrf檔案上傳驗證

cookie import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self):

Spring Boot2(十五):Shiro記住我rememberMe驗證Kaptcha

接著上次學習的《Spring Boot2(十二):手摸手教你搭建Shiro安全框架》,實現了Shiro的認證和授權。今天繼續在這個基礎上學習Shiro實現功能記住我rememberMe,以及登入時驗證碼Kaptcha。 Remember Me記住我:使用者的登入狀態會不會因為瀏覽器的關閉而失效,直到Cooki