Session的时效性——由验证码引出的问题

 

(对jsp servlet tomcat 的理解)

目录

Session的时效性——由验证码引出的问题    1

1、理解JSP、servlet、web容器    1

1.1、Jsp    1

1.2、Servlet    3

1.3、Web容器    6

2、好了,当一切准备工作做完,来看一个结合三者的例子    7

3、好,到此为止 一切准备工作做好了。    9

进入咱们的正题,web加验证码的session 问题    9

 

 

 

1、理解JSP、servlet、web容器

1.1、Jsp

JSP也是一个servlet,sun公司是先设计出servlet后,因为其表达视图不方便,又推出servlet

 

1、它有<%%> 和<!% %> <%=%> 标记和html标记 。

2、JSP九大隐含对象:

request              HttpServletRequest类的实例

response     HttpServletResponse类的实例

out                     PrintWriter类的实例,用于把结果输出至网页上

session        HttpSession类的实例

application ServletContext类的实例,与应用上下文有关

config          ServletConfig类的实例

pageContext     PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问

page          httpJspPage类的实例,类似于Java类中的this关键字

Exception   Exception类的对象,代表发生错误的JSP页面中对应的异常对象

3、还有一些标签库 如 核心标签库,c标签库等

但是万变不离其宗,当你理解到所有的jsp标签代码都能以servlet的形式写出来后,一切就豁然开朗了

一个jsp例子(myeclipse自动生成的)

test.jsp

<%@pagelanguage="java"import="java.util.*"pageEncoding="ISO-8859-1"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

 

<!DOCTYPEHTMLPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<%!int a=1;%>

<%int b=1;%>

<%=a+b%>

</head>

<body>

This is my JSP page.<br>

</body>

</html>

1.2、Servlet

Servlet是java的一系列衍生类,可以狭义的理解为其他java类 Math 类等。它extends HttpServlet 类

 

不得不说它的创建过程

Init()初始化

doPodst()调用方法

doGet()调用方法

destroy()销毁方法

下面贴一个与上面jsp完全一模一样的servlet对应代码

 

test.java

package user;

 

import java.io.IOException;

import java.io.PrintWriter;

 

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

/**

*Servlet implementation class test

*/

@WebServlet("/test")

publicclass testextends HttpServlet {

    privatestaticfinallongserialVersionUID = 1L;

inta=1;//标记2

/**

*@see HttpServlet#HttpServlet()

*/

public test() {

super();

//TODO Auto-generated constructor stub

}

 

    @Override

    publicvoid destroy() {

        //TODO Auto-generated method stub

        super.destroy();

    }

 

    @Override

    publicvoid init() throws ServletException {

        //TODO Auto-generated method stub

        super.init();

    }

 

    /**

     *@see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

    protectedvoid doGet(HttpServletRequest request, HttpServletResponseresponse)throws ServletException, IOException {

        //TODO Auto-generated method stub

        intb=1; //servlet标记1

        PrintWriterout =response.getWriter();

        out.print(a+b);//标记3

    }

 

    /**

     *@see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

     */

    protectedvoid doPost(HttpServletRequest request, HttpServletResponseresponse)throws ServletException, IOException {

        //TODO Auto-generated method stub

        doGet(request,response);

    }

 

}

 

1.3、Web容器

看到这里读者不了解的也许一头雾水,接下来仍要理解一个概念,web容器,我所写的没有废话,当这三个概念写完后,我会将三者利用代码详细解释一下web应用程序的过程

 

Web容器:目前所接触的只有tomcat,要理解web容器,先理解容器是什么

Jvm就是一个容器,它把java文件编译成 字节码文件class 然在jvm(java虚拟机中运行)

这就是一个容器, 运行所有java文件的容器。

再细分,简单的容器,莫过于List Set这些collection,按规则用来装数据的工具。

 

tomcat这样级别的容器,它不仅是装数据了,而且可以产生一些特殊的对象(servlet),让这些对象生存,工作,改变,死亡,并且负责容器和外部服务,或者外部程式的各种相关服务。

而上网的基本原理就是,通过浏览器,发送请求给服务器,得到服务器回应的内容。

但有了web容器,就不用担心浏览器透过http协议传到服务器,是怎么接收,解析这些从网络另外一端传输过来的二进制码;也不用关心,那么多的请求,开发人员该怎么去限制连接数量。这些程式,web容器都已经帮应用开发的人员写好了。应用开发的人员只要舒服的去关注,业务的开发,然后把业务程式部署到web容器里就好了。

   web容器具体的工作如下:

     1。当web服务器接到http请求后,把http协议转给web容器去解析。

     2.web容器创建 HttpServletRequestHttpServletResponseHttpSession等对象。

     3. Web容器由請求的URL決定要使用哪个Servlet來处理請求(事先由开发人員定义)。

     4. Servlet根据请求对象(HttpServletRequest )的信息決定如何处理,透过回应对象(HttpServletResponse )來建立回应。

    5 . Web容器与Web服务器接通,Web服务器将回应转化为HTTP回应并传回客戶端。

 

2、好了,当一切准备工作做完,来看一个结合三者的例子

 

 

 



以上过程一定理解!重要重要重要!

 

3、好,到此为止 一切准备工作做好了。

进入咱们的正题,web加验证码的session 问题

 

验证码源码

package user;

 

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.image.BufferedImage;

import java.io.IOException;

importjava.io.PrintWriter;

import java.util.Random;

 

import javax.imageio.ImageIO;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

 

 

/**

*Servlet implementation class test

*/

@WebServlet("/test")

publicclass testextends HttpServlet {

    privatestaticfinallongserialVersionUID = 1L;

inta=1;

/**

*@see HttpServlet#HttpServlet()

*/

public test() {

super();

//TODO Auto-generated constructor stub

}

 

    @Override

    publicvoid destroy() {

        //TODO Auto-generated method stub

        super.destroy();

    }

 

    @Override

    publicvoid init() throws ServletException {

        //TODO Auto-generated method stub

        super.init();

    }

 

    /**

     *@see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

     */

    protectedvoid doGet(HttpServletRequest request, HttpServletResponseresponse)throws ServletException, IOException {

        //TODO Auto-generated method stub

      

    response.setContentType("image/jpeg");

    response.setHeader("Pragma","No-cache");

    response.setHeader("Cache-Control","no-cache");

    response.setDateHeader("Expires", 0);

     HttpSessionsession =request.getSession();

    //在内存中创建图象

    intwidth = 75,height = 25;

     BufferedImageimage =new BufferedImage(width,height,

     BufferedImage.TYPE_INT_RGB);

    //获取图形上下文

     Graphicsg =image.getGraphics();

    //生成随机类

     Randomrandom =new Random();

    //设定背景色

    g.setColor(getRandColor(200, 250));

    g.fillRect(0, 0,width,height);

    //设定字体

    g.setFont(new Font("Times New Roman", Font.PLAIN, 24));

    //画边框

    g.setColor(getRandColor(160, 200));

    g.drawRect(0, 0,width - 1,height - 1);

    //随机产生155条干扰线,使图象中的认证码不易被其它程序探测到

    g.setColor(getRandColor(160, 200));

    for (inti = 0;i < 155;i++) {

    intx =random.nextInt(width);

    inty =random.nextInt(height);

    intxl =random.nextInt(12);

    intyl =random.nextInt(12);

    g.drawLine(x,y,x +xl,y +yl);

     }

    //取随机产生的认证码(4位数字)

     StringsRand ="";

    for (inti = 0;i < 4; i++) {

     Stringrand = String.valueOf(random.nextInt(10));

    sRand +=rand;

    //将认证码显示到图象中

    g.setColor(new Color(20 +random.nextInt(110), 20 +random

     .nextInt(110), 20 +random.nextInt(110)));

    //调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成

    g.drawString(rand, 13 *i + 14, 20);

      

      

    //将认证码存入SESSION

    session.setAttribute("vcode",sRand);

     }

    //图象生效

    g.dispose();

    //输出图象到页面

     ImageIO.write(image,"JPEG",response.getOutputStream());

      

          

         

        

        

    }

 

    /**

     *@see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

     */

    protectedvoid doPost(HttpServletRequest request, HttpServletResponseresponse)throws ServletException, IOException {

        //TODO Auto-generated method stub

        doGet(request,response);

    }

      

Color getRandColor(intfc,intbc) {//给定范围获得随机颜色

Randomrandom =new Random();

if (fc > 255)

fc = 255;

if (bc > 255)

bc = 255;

intr =fc + random.nextInt(bc -fc);

intg =fc + random.nextInt(bc -fc);

intb =fc + random.nextInt(bc -fc);

returnnew Color(r, g, b);

}

 

}

是一个servlet, 部署好项目并运行后

在地址栏输入 http://localhost:8080/test/test 会出现一张图片

 

先理解其过程

1、运行的是一个servlet,只不过设置返回结果为图片的形式。

2、但是其中有一行代码

session.setAttribute("vcode",sRand);

请注意,是在生成图片的时候,往sessionsetAttribute

如果一个 test2.jsp文件中有以下代码

<% String str=(String)session.getAttribute("vcode");%>

<%=str%>

<ahref="#">

<imgalt="验证码"src="test/test"class="checknum"></a>

 

此时test2.jsp会在web容器中执行<% String str=(String)session.getAttribute("vcode");%>

<%=str%>代码,

此时session中当然没有验证码了,

web全部转化为静态代码后,浏览器才会继续去访问test/test这个servlet

也就是说,是先getAttribute("vcode")然后才setAttribute的,就会出现一个session时效性问题。

理解了原理,解决这个问题就有方法了!

解决这个问题的方法有三种

1、使用ajax技术在页面全部加载后,重新session中获取。

2、使用JavaScript动态加载机制

3、想办法将加载的图片下载到本地,然后再链接到图片!

 


 

至于方法实现,明天写!今天先这样!

2016121722:56:10

        一切都来得及,一切不都会太晚!


2017年3月27日16:47:09   过了3个月了,还没实现当初说的,不过发现一篇更清晰的博客,推荐看看


http://www.bysocket.com/?p=518  泥瓦匠!

                                     QQ570221322 ,欢迎交流!

 

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐