• 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重定向和转发都会失效,你得想办法登录成功后跳转系统页面。虽然都是比较基础的东西,对于初学者来说还是需要好好掌握。

      

  • 相关阅读:
    [PY3]——内置数据结构(2)——元组及其常用操作
    [PY3]——内置数据结构(1)——列表及其常用操作
    [PY3]——基本语法
    session和cookie介绍以及session简单应用
    php中获取当前系统时间、时间戳
    ajax之XML简介
    Ajax练习题
    ajax语法
    JQUERY选中问题
    JSON
  • 原文地址:https://www.cnblogs.com/saule/p/11080112.html
Copyright © 2020-2023  润新知