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重定向和轉發都會失效,你得想辦法登錄成功后跳轉系統頁面。雖然都是比較基礎的東西,對於初學者來說還是需要好好掌握。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM