Servlet+jsp用户登录加上验证码

  最近公司有个项目被客户拿去进行漏洞扫描,发现用户登录太简单,容易被暴力破解。当然发现的问题很多,什么反射型XSS,存储型XSS,敏感信息泄露等等。但是我们今天不讲这么多,就说说如何修复暴力破解的问题。由于登录界面未设置图形验证码,也没有对同一用户在连续登录错误时进行限制,导致攻击者可以尝试破解任意已知用户的密码。所以针对这种情况,第一,对同一用户连续登录在规定时间内的次数进行限制,超过则锁定用户。第二,添加图形验证码。

  首先给你们看看我的项目结构:

user.sql数据:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE user (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(32) NOT NULL COMMENT '密码,加密存储',
  `islocked` varchar(10) DEFAULT "0" COMMENT '是否锁定',
  `firsttime` varchar(50) DEFAULT NULL COMMENT '第一次登录错误时间',
  `count` varchar(10) DEFAULT NULL COMMENT '登录错误次数',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8 COMMENT='用户表';

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO user VALUES (null, 'admin', 'e10adc3949ba59abbe56e057f20f883e', '0', null, null);
INSERT INTO user VALUES (null, 'nanshan', 'e10adc3949ba59abbe56e057f20f883e', '0', null, null);

新建数据库test,导入user.sql即可。

web层:

VerifyCodeServlet.java

package cn.itcast.com.servlet;

import java.io.IOException;

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

import cn.itcast.com.util.VerifyCodeUtils;
/**
 * 
 * @author saule    
 * @date  2019年6月28日 下午11:39:19
 * @Description 验证码servlet
 */
public class VerifyCodeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

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

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        int width = 100;
        int height = 35;
        //获取验证码
        String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
        //将验证码保存到session
        request.getSession().setAttribute("verifyCode", verifyCode);
        //向页面输出验证码
        VerifyCodeUtils.outputImage(width, height, response.getOutputStream(), verifyCode);

    }

}

LoginServlet.java

package cn.itcast.com.servlet;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

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

import net.sf.json.JSONArray;
import cn.itcast.com.pojo.User;
import cn.itcast.com.service.UserService;
/**
 *  正常用户登录流程:
 *    1,判断验证码是否正确。
 *     2,判断用户是否锁定。
 *     3,根据用户名称查找,判断用户是否存在。
 *     4,判断密码是否正确。
 */

public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/xml;charset=utf-8");
        String username=request.getParameter("username");
        String password=request.getParameter("password");
        String vercode=request.getParameter("vercode");
        
        String sessionCode=(String) request.getSession().getAttribute("verifyCode");
        //清除session中的验证码
        request.getSession().removeAttribute("verifyCode");
    
        Map<String,String> map=new HashMap<>();
        //验证码错误
        if(sessionCode!=null && !sessionCode.equals(vercode.toUpperCase())){
            map.put("errcode", "0");
            // 转换成json
            String json = JSONArray.fromObject(map).toString();
            
            response.getWriter().write(json);
            response.getWriter().close();
            return;
        }
        System.out.println(username+":"+password);
        UserService userService=new UserService();
        User loginUser=new User();
        loginUser.setUsername(username);
        loginUser.setPassword(password);
        Map<String, Object> result = userService.login(loginUser);
        if(result.get("errcode").equals("4")){//验证成功
            request.getSession().setAttribute("username", username);
            request.getSession().setAttribute("password", password);
        //用ajax请求用户登录,重定向和转发都是失效的。
//request.getRequestDispatcher("/WEB-INF/success.jsp").forward(request, response); } // 转换成json String json = JSONArray.fromObject(result).toString(); response.getWriter().write(json); response.getWriter().close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

Service层:

UserService.java

package cn.itcast.com.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import cn.itcast.com.dao.UserDao;
import cn.itcast.com.pojo.User;
import cn.itcast.com.util.Md5Utils;
/**
 * 
 * @author saule    
 * @date  2019年6月27日 上午10:50:44
 * @Description
 */
public class UserService {
    private static final String USER_NOT_EXIST="1";
    private static final String USER_IS_LOCK="2";
    private static final String PASSWORD_ERROR="3";
    private static final String VERIFICATION_SUCCESS="4";
    
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    //登录操作
    public Map<String,Object> login(User loginUser) {
        Map<String,Object> loginMap=new HashMap<String, Object>();
        UserDao userDao=new UserDao();
        User user=userDao.findByName(loginUser.getUsername());
        String pwd = Md5Utils.md5(loginUser.getPassword());
        
        if(user==null){//用户不存在
            loginMap.put("errcode", USER_NOT_EXIST);
            
        }else if(user.getIslocked().equals("1")){//用户被锁定
            loginMap.put("errcode", USER_IS_LOCK); 
            
        }else if(!user.getPassword().equals(pwd)){//密码错误
            //超过规定时间,次数不超过4次登录时,将时间与次数重置。
            if(user.getFirsttime()!=null){
                try {
                    long firsttime=sdf.parse(user.getFirsttime()).getTime();
                    long nowtime=new Date().getTime();
                    if((nowtime-firsttime)>5*60*1000){
                        user.setFirsttime(null);
                        user.setCount("0");
                        userDao.update(user);
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            
            if(user.getFirsttime()==null){//初次登录密码错误,记录数据。
                user.setFirsttime(sdf.format(new Date()));
                user.setCount("1");
                userDao.update(user);
            }else if(user.getFirsttime()!=null && Integer.valueOf(user.getCount())<3){//连续登陆错误次数小于4次
                String newCount = String.valueOf(Integer.valueOf(user.getCount())+1);
                user.setCount(newCount);
                userDao.update(user);
                
            }else{//大于4次且时间间隔小于5分钟则锁定用户。禁止登录。
                try {
                    long firsttime=sdf.parse(user.getFirsttime()).getTime();
                    long nowtime=new Date().getTime();
                    if((nowtime-firsttime)<5*60*1000){
                        user.setFirsttime(null);
                        user.setCount("0");
                        user.setIslocked("1");//1表示锁定用户
                        userDao.update(user);
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            loginMap.put("errcode", PASSWORD_ERROR); 
            loginMap.put("user", user);
        }else{
            loginMap.put("errcode", VERIFICATION_SUCCESS);
        }
        return loginMap;
    }

}

Dao层:

UserDao.java

package cn.itcast.com.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import cn.itcast.com.pojo.User;
import cn.itcast.com.util.JdbcUtils;

public class UserDao {

    //根据用户查询
    public User findByName(String username) {
        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;
        String sql="select * from user where username=?";
        try {
            conn=JdbcUtils.getConnection();
            pst=conn.prepareStatement(sql);
            pst.setString(1, username);
            
            rs=pst.executeQuery();
            
            if(rs.next()){
                User user=new User();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
                user.setIslocked(rs.getString("islocked"));
                user.setFirsttime(rs.getString("firsttime"));
                user.setCount(rs.getString("count"));
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                JdbcUtils.close(conn, pst, rs);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        return null;
    }

    //修改用户信息
    public void update(User user) {
        Connection conn=null;
        PreparedStatement pst=null;
        String sql="update user set islocked=?,firsttime=?,count=? where id=?";
        
        try {
            conn=JdbcUtils.getConnection();
            pst = conn.prepareStatement(sql);
            pst.setString(1, user.getIslocked());
            pst.setString(2, user.getFirsttime());
            pst.setString(3, user.getCount());
            pst.setInt(4, user.getId());
            int row = pst.executeUpdate();
            if(row!=0){
                System.out.println("修改成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                JdbcUtils.close(conn, pst, null);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
    }

}

实体类:

user.java

package cn.itcast.com.pojo;

public class User {
    private Integer id;
    private String username;
    private String password;
    private String islocked;//是否锁定,0表示没有锁定;1表示锁定;
    private String firsttime;
    private String count;//连续登录错误次数
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getIslocked() {
        return islocked;
    }
    public void setIslocked(String islocked) {
        this.islocked = islocked;
    }
    public String getFirsttime() {
        return firsttime;
    }
    public void setFirsttime(String firsttime) {
        this.firsttime = firsttime;
    }
    public String getCount() {
        return count;
    }
    public void setCount(String count) {
        this.count = count;
    }
    
    

}

帮助类:

VerifyCodeUtils.java

package cn.itcast.com.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;

/**
 * 验证码生成工具
 * @author zl
 */

public class VerifyCodeUtils{

    //使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
    public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
    private static Random random = new Random();


    /**
     * 使用系统默认字符源生成验证码
     * @param verifySize    验证码长度
     * @return
     */
    public static String generateVerifyCode(int verifySize){
        return generateVerifyCode(verifySize, VERIFY_CODES);
    }
    /**
     * 使用指定源生成验证码
     * @param verifySize    验证码长度
     * @param sources   验证码字符源
     * @return
     */
    public static String generateVerifyCode(int verifySize, String sources){
        if(sources == null || sources.length() == 0){
            sources = VERIFY_CODES;
        }
        int codesLen = sources.length();
        Random rand = new Random(System.currentTimeMillis());
        StringBuilder verifyCode = new StringBuilder(verifySize);
        for(int i = 0; i < verifySize; i++){
            verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));
        }
        return verifyCode.toString();
    }

    /**
     * 生成随机验证码文件,并返回验证码值
     * @param w
     * @param h
     * @param outputFile
     * @param verifySize
     * @return
     * @throws IOException
     */
    public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{
        String verifyCode = generateVerifyCode(verifySize);
        outputImage(w, h, outputFile, verifyCode);
        return verifyCode;
    }

    /**
     * 输出随机验证码图片流,并返回验证码值
     * @param w
     * @param h
     * @param os
     * @param verifySize
     * @return
     * @throws IOException
     */
    public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{
        String verifyCode = generateVerifyCode(verifySize);
        outputImage(w, h, os, verifyCode);
        return verifyCode;
    }

    /**
     * 生成指定验证码图像文件
     * @param w
     * @param h
     * @param outputFile
     * @param code
     * @throws IOException
     */
    public static void outputImage(int w, int h, File outputFile, String code) throws IOException{
        if(outputFile == null){
            return;
        }
        File dir = outputFile.getParentFile();
        if(!dir.exists()){
            dir.mkdirs();
        }
        try{
            outputFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(outputFile);
            outputImage(w, h, fos, code);
            fos.close();
        } catch(IOException e){
            throw e;
        }
    }

    /**
     * 输出指定验证码图片流
     * @param w
     * @param h
     * @param os
     * @param code
     * @throws IOException
     */
    public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{
        int verifySize = code.length();
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Random rand = new Random();
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        Color[] colors = new Color[5];
        Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,
                Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
                Color.PINK, Color.YELLOW };
        float[] fractions = new float[colors.length];
        for(int i = 0; i < colors.length; i++){
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
            fractions[i] = rand.nextFloat();
        }
        Arrays.sort(fractions);

        g2.setColor(Color.GRAY);// 设置边框色
        g2.fillRect(0, 0, w, h);

        Color c = getRandColor(200, 250);
        g2.setColor(c);// 设置背景色
        g2.fillRect(0, 2, w, h-4);

        //绘制干扰线
        Random random = new Random();
        g2.setColor(getRandColor(160, 200));// 设置线条的颜色
        for (int i = 0; i < 20; i++) {
            int x = random.nextInt(w - 1);
            int y = random.nextInt(h - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
        }

        // 添加噪点
        float yawpRate = 0.05f;// 噪声率
        int area = (int) (yawpRate * w * h);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(w);
            int y = random.nextInt(h);
            int rgb = getRandomIntColor();
            image.setRGB(x, y, rgb);
        }

        shear(g2, w, h, c);// 使图片扭曲

        g2.setColor(getRandColor(100, 160));
        int fontSize = h-4;
        Font font = new Font("Algerian", Font.ITALIC, fontSize);
        g2.setFont(font);
        char[] chars = code.toCharArray();
        for(int i = 0; i < verifySize; i++){
            AffineTransform affine = new AffineTransform();
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);
            g2.setTransform(affine);
            g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);
        }

        g2.dispose();
        ImageIO.write(image, "jpg", os);
    }

    private static Color getRandColor(int fc, int bc) {
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    private static int getRandomIntColor() {
        int[] rgb = getRandomRgb();
        int color = 0;
        for (int c : rgb) {
            color = color << 8;
            color = color | c;
        }
        return color;
    }

    private static int[] getRandomRgb() {
        int[] rgb = new int[3];
        for (int i = 0; i < 3; i++) {
            rgb[i] = random.nextInt(255);
        }
        return rgb;
    }

    private static void shear(Graphics g, int w1, int h1, Color color) {
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    }

    private static void shearX(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(2);

        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i = 0; i < h1; i++) {
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                    + (6.2831853071795862D * (double) phase)
                    / (double) frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) {
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            }
        }

    }

    private static void shearY(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(40) + 10; // 50;

        boolean borderGap = true;
        int frames = 20;
        int phase = 7;
        for (int i = 0; i < w1; i++) {
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                    + (6.2831853071795862D * (double) phase)
                    / (double) frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) {
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            }

        }

    }
    public static void main(String[] args) throws IOException{
        File dir = new File("F:/verifies");
        int w = 200, h = 80;
       
        String verifyCode = generateVerifyCode(4);
        File file = new File(dir, verifyCode + ".jpg");
        outputImage(w, h, file, verifyCode);
    }
}

 Md5Utils.java

package cn.itcast.com.util;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Md5Utils {
    /**
     * 使用md5的算法进行加密
     */
    public static String md5(String plainText) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                    plainText.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有md5这个算法!");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字
        // 如果生成数字未满32位,需要前面补0
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }
}

JdbcUtils.java

package cn.itcast.com.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;

/**
 * @author saule    
 * @date  2019年6月27日 上午10:23:58
 * @Description JDBC帮助类
 */

public class JdbcUtils {

    private static String driver="com.mysql.jdbc.Driver";
    private static String url="jdbc:mysql://localhost:3306/test?characterEncoding=utf-8";
    private static String username="root";
    private static String password="root";


    static {
        try {
            // 将加载驱动操作,放置在静态代码块中.这样就保证了只加载一次.
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
        //获取连接
        Connection con = DriverManager.getConnection(url, username, password);

        return con;
    }
    
    //关闭操作
    public static void close(Connection con,Statement st,ResultSet rs) throws SQLException{
        if(con!=null){
            con.close();
        }else if(st!=null){
            st.close();
        }else if(rs!=null){
            rs.close();
        }
    }
    
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>youdu</display-name>
  <servlet>
    <servlet-name>VerifyCodeServlet</servlet-name>
    <servlet-class>cn.itcast.com.servlet.VerifyCodeServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>cn.itcast.com.servlet.LoginServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>VerifyCodeServlet</servlet-name>
    <url-pattern>/getVerifyCode</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
  </welcome-file-list>
</web-app>

前端页面:

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录页面</title>
<style type="text/css">
        #login{
            border: 1px solid deepskyblue;
            background-color: blanchedalmond;
            width:400px;
            height:250px;
            padding-left: 100px;
            padding-top: 50px;
        }
 
    </style>
    <script type="text/javascript">
        //创建一个ajax对象
        function getLoginAjax(){
            var loginRequest;
            if(window.XMLHttpRequest){
                loginRequest=new XMLHttpRequest();
            }else if(window.ActiveXObject){//window对象中有ActiveXObject属性存在就是IE浏览器的低版本
                try{
                    loginRequest= new ActiveXObject("Msxml2.XMLHTTP");
                }catch(e){
                    loginRequest= new ActiveXObject("Microsoft.XMLHTTP");
                }
            }
            return loginRequest;
        }
        
        //登录方法
        function userlogin(){
            //获取参数
            var username=document.getElementById("username").value;
            var password=document.getElementById("password").value;
            var vercode=document.getElementById("vercode").value;
            /* 此处省略非空校验 */
            var loginAjax=getLoginAjax();
            
            loginAjax.open("POST", "login", true);
            //请求头
            loginAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
            loginAjax.send("username="+username+"&password="+password+"&vercode="+vercode);
            //设置回调函数
            loginAjax.onreadystatechange = function() {
                //处理响应数据  当信息全部返回,并且是成功
                if (loginAjax.readyState == 4 && loginAjax.status == 200) {
                    //返回的数值类型一般是json格式,比较常见
                    console.log();
                    var jsonObj = eval("(" + loginAjax.responseText + ")");
                    
                    for(var i=0;i<jsonObj.length;i++){
                        var errcode = jsonObj[i].errcode;
                        if(errcode==0){
                            alert("验证码错误");
                            identifyload();
                            return false;
                        }else if(errcode==1){
                            alert("用户不存在");
                            identifyload();
                            return false;
                        }else if(errcode==2){
                            alert("用户被锁定,请联系管理。");
                            return false;
                        }else if(errcode==3){
                            var user = jsonObj[i].user;
                            var locked=user.islocked;
                            var count=user.count;
                            if(locked=='0' && count<4){
                                alert("密码错误,你还有"+(4-count)+"次机会");
                                identifyload();
                            }else if(locked=='1'){
                                alert("用户被锁定,请联系管理。");
                            }
                            return false;
                        }else if(errcode==4){
                            alert("登录成功");
                            window.location="http://localhost:8080/youdu/success.jsp";
                        }
                    }
                    
                    

                }
            };
        }
        
        
       
       function identifyload() {
            document.getElementById("imgcode").src = 'getVerifyCode?nowtime='+ new Date().getTime();
       }
    </script>
</head>
<body>
<div  id="login">
    <form action="./login" method="Post" name="login">
    <table>
        <tr>
            <td>用户名:</td>
            <td>
                <input name="username" type="text" placeholder="请输入昵称" id="username"/><br/><br/>
            </td>
        </tr>
        <tr>
            <td>密码:</td>
            <td>
                <input name="password" type="password" placeholder="请输入密码" id="password"/><br/><br/>
            </td>
        </tr>
        <tr>
            <td>验证码:</td>
            <td>
                <input name="vercode" type="text" id="vercode"/>
                <img src="./getVerifyCode" height="32" id="imgcode" onclick="identifyload()" title="点击更换验证码">
            </td>
        </tr>
        <tr>
            <td height="20">&nbsp;</td>
        </tr>
        
        <tr>
            <td>
                <button type="button" value="登录" onclick="userlogin()">登录</button>
                <button type="reset" value="重置">重置</button>
            </td>
        </tr>
    </table>
    </form>
</div>
</body>
</html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>登录成功</h3>
用户名:${sessionScope.username}
密码:${sessionScope.password}
</body>
</html>

 来个效果图:

最后说几句。虽然用户登录流程简单,但是用servlet和原生js、ajax实现还是有些坑的,特别是现在个个都习惯在框架下写代码,就比如ajax请求后,servlet重定向和转发都会失效,你得想办法登录成功后跳转系统页面。虽然都是比较基础的东西,对于初学者来说还是需要好好掌握。

  

猜你喜欢

转载自www.cnblogs.com/saule/p/11080112.html
今日推荐