session 学习-为登录添加验证码

本文介绍了如何利用session和验证码实现登录验证。在登录过程中,验证通过后将用户信息存入session,对于受保护资源,检查session中的用户信息以决定访问权限。详细步骤包括验证码生成、session操作、session超时及限制的设置,并讨论了session的优缺点。

问题

保存登录信息,保护某些资源只有在登录验证之后才能访问.

方案

登录信息提交后进行验证,验证通过则将用户信息保存在session中,验证失败则转发回登录页面。对于需要保护的资源,添加从session中获取绑定值的功能,以判断是否能够成功获取绑定的用户信息为判断依据,获取到则代表已验证,则允许访问,获取不到绑定在session中的用户信息,代码验证没有通过,则拒绝访问该资源,而将请求重定向到登陆页面。

步骤

step1 :新建login.jsp页面

<%@ page contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Login</title>
    <!--鼠标移入图片,变成手的形状 -->
    <style type="text/css">
        .s1{
            cursor:pointer;  
        }
    </style>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>

  <body>
    <h2>登录</h2>
    <form action="login.do" method="post">
        用户名:<input name="uname"/><br><br>
        密     码:<input name="pwd" type="password"/><br><br>
         验证码: <input name="vcode"/>
        <img src="code" onclick="this.src='code?'+Math.random();"
        class="s1" title="点击更换"><br><br>
        <input type="submit" value="登录"/>

    </form>
  </body>
</html>

界面如下:
登陆

step2 新建ActionServlet类

package web;

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;
import javax.servlet.http.HttpSession;

public class ActionServlet extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //保证正确读取Post提交来的中文
        request.setCharacterEncoding("UTF-8");
        //保证正确输出中文
        response.setContentType("text/html;charset=UTF-8");
        //获取uri,并截取action动作
        String uri=request.getRequestURI();
        String action=uri.substring(uri.lastIndexOf("/")+1,
                uri.lastIndexOf("."));
        //获取session
        //HttpSession session=request.getSession();
        //System.out.println(session.getId());
        //设定session超时时间为10秒
        //session.setMaxInactiveInterval(10);
        //判断动作是否为登录
        if(action.equals("login")){
            String name=request.getParameter("uname");
            String pwd=request.getParameter("pwd");
            String number=request.getParameter("vcode");
            HttpSession session=request.getSession();
            //要求大小写一致
            String code = (String)session.getAttribute("code").toString();
            if(number.equals(code)&&name.equals("111")&&pwd.equals("111")){
                //绑定数据
                session.setAttribute("uname", name);
                //重定向到首页
                //response.sendRedirect("index.jsp");
                //使用URL重写的方法,改写原本的访问地址
                response.sendRedirect(
                        response.encodeRedirectURL("index.jsp"));
            }else{
                //登录失败
                request.setAttribute("msg", "用户名或密码错误");
                request.getRequestDispatcher("login.jsp")
                    .forward(request, response);
            }
        }else if(action.equals("logout")){
            HttpSession session=request.getSession();
            //session失效
            session.invalidate();
            response.sendRedirect("login.jsp");
        }

        PrintWriter out = response.getWriter();
        out.close();
    }

}

step3. 新建 ValidateCode.java
生成验证码

package web;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
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;
import javax.servlet.http.HttpSession;

public class ValidateCode extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //0.创建空白图片
        BufferedImage image=new BufferedImage(100,30,BufferedImage.TYPE_INT_RGB);
        //1.获取图片画笔
        Graphics g = image.getGraphics();
        Random r=new Random();
        //2.设置画笔颜色(Random类中的nextInt(n)返回一个大于等于0,小于n的随机数)
        g.setColor(new Color(r.nextInt(255),r.nextInt(255), r.nextInt(255)));
        //3.绘制矩形的背景
        g.fillRect(0, 0, 100, 30);
        //4.调用自定义的方法,获取长度为5的字母数字组合的字符串
        String number=getNumber(5);
        HttpSession session=request.getSession();
        session.setAttribute("code", number);
        g.setColor(new Color(0,0,0));
        g.setFont(new Font(null,Font.BOLD,24));
        //5.设置颜色字体后,绘制字符串(x/y,最左边字符所处的位置)
        g.drawString(number, 8, 24);
        //6.绘制8条干扰线(alpha表示透明度)
        for(int i=0;i<8;i++){
            g.setColor(new Color(r.nextInt(255),r.nextInt(255), r.nextInt(255),r.nextInt(255)));
            g.drawLine(r.nextInt(100), r.nextInt(30), r.nextInt(100), r.nextInt(30));
        }
        response.setContentType("image/jpeg");
        OutputStream ops = response.getOutputStream();
        ImageIO.write(image, "jpeg", ops);
        ops.close();
    }
    //自定义方法,获取长度为5的字母数字组合的字符串
    private String getNumber(int size){
        String str="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String number="";
        Random r=new Random();
        for(int i=0;i<size;i++){
            number+=str.charAt(r.nextInt(str.length()));
        }
        return number;
    }

}

step4. 配置web.xml

  <servlet>
    <servlet-name>ActionServlet</servlet-name>
    <servlet-class>web.ActionServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ValidateCode</servlet-name>
    <servlet-class>web.ValidateCode</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ActionServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ValidateCode</servlet-name>
    <url-pattern>/code</url-pattern>
  </servlet-mapping>    

step4. 新建index.jsp
登陆成功时,进入的界面

<%@ page contentType="text/html;charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

    <title>Login successed</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

    <%
        //session验证
        Object uname=session.getAttribute("uname");
        if(uname==null){
            response.sendRedirect("login.jsp");
            return;
        }
     %>
  </head>

  <body>
     <h3>首页</h3>欢迎你:<%=uname.toString()%><br><br>

     <a href="logout.do">退出</a>
  </body>
</html>

成功登陆后,进入的页面
登陆成功


对于上面项目中用到的代码,下面做一个只是梳理。
1、如何删除session对象
立即删除session对象;

session.invalidate();

2、session验证
用户访问需要保护的资源时,可以使用session验证的方式来保证其安全性,比如要求登陆后才能访问的资源
实现session验证,遵循以下步骤

  • 使用session.setAttribute()先绑定数据
  • 使用session.getAttribute()方式来读取绑定值,如果没有,则跳转回登录页面

3、什么是session超时

  • Web服务器会将空闲时间过长的session对象删除掉,以节省服务器内存空间资源
  • Web服务器缺省的超时时间限制:一般是30分钟

4、修改session的缺省时间限制
编程方式:

void session.setMaxInactiveInterval(int seconds);

修改web.xml的方式:

 <session-config>
     <session-timeout>30</session-timeout>
 </session-config>  

5、session的优缺点
优点

  • 安全(将状态保存在服务器端)
  • session能够保存的数据类型更丰富,Cookie只能保存字符串
  • session能够保存更多的数据,Cookie大约保存4k

缺点
session将状态保存在服务器端,占用服务器的内存,如果用户量过大,会严重影响服务器的性能

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值