最近公司有个项目被客户拿去进行漏洞扫描,发现用户登录太简单,容易被暴力破解。当然发现的问题很多,什么反射型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);//将验证码保存到sessionrequest.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");// 转换成jsonString 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);
        }// 转换成jsonString 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位,需要前面补0for (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重定向和转发都会失效,你得想办法登录成功后跳转系统页面。虽然都是比较基础的东西,对于初学者来说还是需要好好掌握。

  

转载于:https://www.cnblogs.com/saule/p/11080112.html

Servlet+jsp用户登录加上验证码相关推荐

  1. 基于 JSP + Servlet 的用户登录验证

    综合案例--基于 JSP + Servlet 的用户登录验证 [例6-1] 实现一个简单的用户登录验证程序,如果用户名是 abc ,密码是 123,则显示欢迎用户的信息,否则显示"用户名或密 ...

  2. java servlet 注册登录,JSP+JavaBean+Servlet实现用户登录与注册

    数据库 create database student; use student; create table user( id int primary key auto_increment, user ...

  3. servlet实现用户登录

    最近在做课程设计,之前有人问我用户登录的实现,刚又有同学问到,于是我决定还把这个问题的实现写一下吧,免得要一遍一遍的去讲--原谅我的懒惰=_= ============================ ...

  4. jsp用session判断输入框_[实战小剧场servletamp;jsp] 用户登录及退出功能实现

    项目使用技术:servlet+jsp+mybatis 用户登录: 根据用户名和密码查询用户信息.查到则登录成功,查不到则登录失败. 用户退出: 销毁session 登录思路: 浏览器在登录页面发起登录 ...

  5. html退出登录_[实战小剧场servletamp;jsp] 用户登录及退出功能实现

    项目使用技术:servlet+jsp+mybatis 用户登录: 根据用户名和密码查询用户信息.查到则登录成功,查不到则登录失败. 用户退出: 销毁session 登录思路: 浏览器在登录页面发起登录 ...

  6. .NET Core实战项目之CMS 第十六章 用户登录及验证码功能实现

    前面为了方便我们只是简单实现了基本业务功能的增删改查,但是登录功能还没有实现,而登录又是系统所必须的,得益于 ASP.NET Core的可扩展性因此我们很容易实现我们的登录功能.今天我将带着大家一起来 ...

  7. JSP用户登录连接数据库

    项目预览图片: 文章最后有对应的介绍和更多截图 等待资源审核,审核后公布代码链接 资源连接:https://download.csdn.net/download/justleavel/21922817 ...

  8. PHP用户登录界面验证码显示为“X”(验证码图片无法显示)解决办法

    1.验证码显示为"X". 2.代码浏览: 1> Login.php代码,经检查,没有问题! <?php    require_once "common.php ...

  9. Servlet——简单用户登录实例+http协议解析

    编写项目.用户登录系统1.0版本号 登录界面Servlet: package com.gavin.view;import java.io.IOException; import java.io.Pri ...

最新文章

  1. Docker搭建Nacos1.3+Seata1.4+MySQL8分布式事务(服务端)
  2. cigarettes(香烟)
  3. (三) UART 串口通讯
  4. go 初学者 错误_初学者的颠簸之旅,发现了一些不错的错误
  5. 微信iOS 7.0.9版本更新:今天的朋友圈是一片欢乐的海洋!
  6. Windows环境下通过lynx查看隐藏链接识别黑链方法
  7. 美国西海岸php,美国西海岸大学top 14
  8. C# 词法分析器(四)构造 NFA
  9. Backbone.js Wine Cellar 教程
  10. 电脑重启桌面 计算机图标消失,电脑重启后桌面图标不见了怎么解决
  11. 网站头像: favicon.ico
  12. 生物信息学算法之Python实现|Rosalind刷题笔记:005 GC含量计算
  13. Python网络爬虫反爬破解策略实战
  14. 探索跨平台应用开发的最佳实践
  15. 致凯利定理(Cayley公式)
  16. 关于虾皮无货源一件代发你了解多少?详讲虾皮物流发货流程
  17. 七牛 回调 java_七牛回调验证(java,php源码)
  18. 电脑上怎么查看邮件服务器,教您如何查看电子邮件头 -电脑资料
  19. 为什么业务中很少用到设计模式
  20. 当你的才华撑不起你的野心的时候,你就应该努力

热门文章

  1. Linux 查询股价工具,find 查找工具
  2. matlab数字图像处理大作业_线上教学优秀案例(16) | 数字图像处理基于蓝墨云+企业微信的线上教学经验分享...
  3. js return 闭包为null_那么如何让你的 JS 写得更漂亮?
  4. java怎么输出liststring_春招|春招实习上岸,分享面筋回报社区(Java、Python)...
  5. android 10闪退如何解决,安卓Activity启动在10.0下闪退
  6. sql选择题_SQL选择
  7. log4j.properties文件示例
  8. Java开发技术有哪些?
  9. 开课吧Java课堂:如何使用isAlive()和join()
  10. cobbler批量安装linux