当前位置:网站首页>小项目(servelt+jsp+mysql+EL+JSTL)完成一个登录功能的Servlet,具有增删改查的操作。实现登录身份验证,防止非法登录,防止多点登录,记住用户名密码功能。
小项目(servelt+jsp+mysql+EL+JSTL)完成一个登录功能的Servlet,具有增删改查的操作。实现登录身份验证,防止非法登录,防止多点登录,记住用户名密码功能。
2022-07-03 13:28:00 【aigo-2021】
小项目(servelt+jsp+mysql+EL+JSTL)完成一个登录功能的Servlet,具有增删改查的操作。实现登录身份验证,防止非法登录,防止多点登录,记住用户名密码功能。
项目框架

1.创建数据库表
login表
create table emp(
empid int(8) auto_increment primary key,
empname varchar(32),
job varchar(255),
salary float(9,2),
tel varchar(11) unique
);
insert into emp
values
(default,'tom','程序员',10000.5,'13553126224'),
(default,'jack','程序员',9000,'13553156224'),
(default,'张良','销售员',15000,'13553123456'),
(default,'王丽丽','销售员',15000,'18253123456');在数据库中存储密码时,要进行加密。加密使用MD5算 法进行加密,MD5算法的特点是,一个字符串通过MD5算法加密后,会得到一个唯一对应的字符串;MD5算法加 密后获得的字符串是不可逆的;通过加盐的方式,让加密的密码更安全。
2.创建Users类
package com.hyxy.emp.vo;
public class Users {
private String loginname;
private String passwd;
private String username;
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
3.Emp.java
package com.hyxy.emp.vo;
public class Emp {
//属性名要和表中的列名相同,可忽略大小写
private int empid;
private String empname;
private String job;
private double salary;
private String tel;
public int getEmpid() {
return empid;
}
public void setEmpid(int empid) {
this.empid = empid;
}
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
}
4.EmpServlet.java
package com.hyxy.emp.servlet;
import com.hyxy.emp.vo.Emp;
import com.oracle.jdbc.util.Dao;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
@WebServlet("/emp.do")//用.do区分servlet的路径
public class EmpServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");//设置客户端浏览器解码字符集
//resp.setCharacterEncoding("UTF-8"); //设置传输内容的编码字符集,浏览器使用相同的字符集才能解码
//System.out.println("调用Dao,获得数据,拼html发给浏览器");
//获得请求的操作标志值
//判断session中是否有key是user的对象,如果没有则向登陆界面进行重定向跳转
HttpSession session=req.getSession();
if(session.getAttribute("user")==null){
PrintWriter pw= resp.getWriter();
pw.println("<script>");
pw.println("window.parent.location.href='"+req.getContextPath()+"/index'");//执行js跳转
//pw.println("window.parent.location.href='${pageContext.request.contextPath}/index'");//执行js跳转
pw.println("</script>");
return;
//resp.sendRedirect();
}
String op=req.getParameter("op");
if("query".equals(op)){
//查询请求的处理
query(req,resp);
}else if("add".equals(op)){
add(req,resp);
}else if("save".equals(op)){
save(req,resp);
}else if("delete".equals(op)){
delete(req,resp);
}else if("edit".equals(op)){
edit(req,resp);
}else if("update".equals(op)){
update(req,resp);
}else if("back".equals(op)){
back(req,resp);
}
}
/**
* 将方法封装
* @param req
* @param resp
*/
protected void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//查询
String sql="select * from emp";
List<Emp> list = Dao.query(sql,Emp.class);
//使用JSP便于代码维护
req.setAttribute("list",list);
req.getRequestDispatcher("/view/emp/query.jsp").forward(req,resp);
}
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/view/emp/add.jsp").forward(req,resp);
}
protected void save(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//接收请求的参数,也就是要保存的数据
String empname= req.getParameter("empname");
String job= req.getParameter("job");
String salary= req.getParameter("salary");
String tel= req.getParameter("tel");//注意电话号码是唯一约束,不能相同,否则报错
//向数据库插入数据
String sql ="insert into emp values(default,?,?,?,?)";
Dao.executeSql(sql,empname,job,salary,tel);
//向浏览器返回插入后的查询数据,调用query,显示查询页面的数据
query(req, resp);
}
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String empid =req.getParameter("id");
String sql="delete from emp where empid=?";
Dao.executeSql(sql,empid);
query(req, resp);
}
protected void edit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String empid = req.getParameter("id");
String sql = "select * from emp where empid = ?";
Emp e = Dao.queryOne(sql,Emp.class,empid);
req.setAttribute("emp",e);
req.getRequestDispatcher("/view/emp/edit.jsp").forward(req,resp);
}
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String empname= req.getParameter("empname");
String job= req.getParameter("job");
String salary= req.getParameter("salary");
String tel= req.getParameter("tel");
String empid = req.getParameter("empid");//用表单隐藏
String sql ="update emp set empname=?,job=?,salary=?,tel=? where empid=?";
Dao.executeSql(sql,empname,job,salary,tel,empid);
//向浏览器返回插入后的查询数据,调用query,显示查询页面的数据
query(req, resp);
}
protected void back(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
框架页面设计
index.html
<!doctype html>
<html lang="en">
<head>
</head>
<frameset rows="100,*">
<frame src="/emp/view/frame/top.html">
<frameset cols="120,*">
<frameset rows="50%,50%">
<frame src="/emp/view/frame/catalog.html" name="left">
</frameset>
<frame src="/emp/view/frame/main.html" name="mainFrame">
</frameset>
</frameset>
</html>
catalog.html 框架左侧目录
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>目录</title>
</head>
<body>
<h2 align='center'>目录</h2>
<table align='center'>
<tr align='center'>
<td align='center'>
<a href="/emp/emp.do?op=query" target="mainFrame">员工管理</a><br>
</td><!--将内容1⽂件的内容指定显⽰给名为rightdown的框架-->
</tr>
<tr align='center'>
<td align='center'>
<a href="/emp/dept.do?op=query" target="mainFrame">部门管理</a><br>
</td>
</tr>
</table>
</body><!--上边的target为指定-->
</html>一、实现登录身份验证功能
1.设计登录界面 IndexServlet.java处理访问登录页面的请求
package com.hyxy.emp.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//输入http://localhost:8080/emp/index访问登录页面
req.setCharacterEncoding("GBK");
resp.setCharacterEncoding("GBK");
Cookie[] cookies=req.getCookies();//获得一个cookie数组
String loginname="";
String passwd="";
String rememberMe="";
for(Cookie cookie:cookies){
if("rememberMe".equals(cookie.getName())){
rememberMe=cookie.getValue();
}
}
if("1".equals(rememberMe)){
for(Cookie cookie:cookies){
if("loginname".equals(cookie.getName())){
loginname=cookie.getValue();
}
if("passwd".equals(cookie.getName())){
passwd=cookie.getValue();
}
}
}
PrintWriter pw= resp.getWriter();
pw.println("<!doctype html>");
pw.println("<html>");
pw.println(" <head>");
pw.println(" <script>");
if(req.getAttribute("msg")!=null){
pw.println("alert('"+req.getAttribute("msg")+"');");
}
pw.println(" function login(){");
pw.println(" var loginname = document.getElementById('loginname');");
pw.println(" var passwd = document.getElementById('passwd');");
pw.println(" if(loginname.value==''){");
pw.println(" alert('请输入用户名');");
pw.println(" return;");
pw.println(" }");
pw.println(" if(passwd.value==''){");
pw.println(" alert('请输入密码');");
pw.println(" return;");
pw.println(" }");
pw.println(" loginForm.submit();");
pw.println(" }");
pw.println(" </script>");
pw.println(" </head>");
pw.println(" <body>");
pw.println(" <form name='loginForm' method='post' action='"+req.getContextPath()+"/login'>");
pw.println(" <table width='60%' align='center'>");
pw.println(" <tr>");
pw.println(" <td align='right'>用户名:</td>");
pw.println(" <td align='left'><input type='text' id='loginname' name='loginname' value='"+loginname+"'></td>");
pw.println(" </tr>");
pw.println(" <tr>");
pw.println(" <td align='right'>密 码:</td>");
pw.println(" <td align='left'><input type='password' id='passwd' name='passwd' value='"+passwd+"'></td>");
pw.println(" </tr>");
pw.println(" <tr>");
pw.println(" <td align='right'><input type='button' value='登录' onclick='login();'></td>");
pw.println(" <td align='left'><input type='checkbox' "+("1".equals(rememberMe)?"checked":"")+" name='rememberMe' value='1'>记住用户名密码</td>");
pw.println(" </tr>");
pw.println(" </table>");
pw.println(" </form>");
pw.println(" </body>");
pw.println("</html>");
}
}
2.LoginServlet.java处理登录身份认证请求
package com.hyxy.emp.servlet;
import com.hyxy.emp.vo.Users;
import com.oracle.jdbc.util.Dao;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.List;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("GBK");
resp.setCharacterEncoding("GBK");
//功能一:登录身份认证
String loginname=req.getParameter("loginname");
String passwd=req.getParameter("passwd");
String rememberMe=req.getParameter("rememberMe");
//如果选中记住用户名密码勾选框,rememberMe的值是1
//将用户输入的登录名和密码在数据库中进行查找
String sql="select * from users where loginname=? and passwd=md5(?)";//第二个?是用户名加密码
List<Users> list = Dao.query(sql,Users.class,loginname,loginname+passwd);
if(list==null||list.size()==0){
//未找到,登录失败
//显示登陆页面,调用IndexServlet对象的service方法(无法实现),使用跳转
// 给出提示
//向IndexServlet进行跳转,使用请求转发跳转
req.setAttribute("msg","登录失败!");//存到Map中,msg是key,后面是value
req.getRequestDispatcher("/index").forward(req,resp);
}else{
//登录成功,重定向跳转
//显示主页面,LoginServlet
// resp.sendRedirect(req.getContextPath()+"/view/index.html");
//功能二:防止非法登录
//例如直接在浏览器输入链接http://localhost:8080/emp/emp.do?op=edit&id=2就能修改表中信息,不需要经过登陆界面
//实现方法,在每个页面都添加session进行判断,否则返回登陆界面
HttpSession session=req.getSession();
session.setAttribute("user",list.get(0));
ServletContext servletContext=this.getServletContext();
if(servletContext.getAttribute(loginname)!=null){
HttpSession otherSession=(HttpSession)servletContext.getAttribute(loginname);
if(!session.getId().equals(otherSession.getId())){//防止当前同一个用户登录多次时,自己将自己踢出
otherSession.invalidate();
}
}
servletContext.setAttribute(loginname,session);
if(rememberMe!=null){
Cookie cookie=new Cookie("loginname",loginname);
cookie.setMaxAge(60*60*24*30);
resp.addCookie(cookie);
cookie=new Cookie("passwd",passwd);
cookie.setMaxAge(60*60*24*30);
resp.addCookie(cookie);
}
Cookie cookie=new Cookie("rememberMe",rememberMe);
cookie.setMaxAge(60*60*24*30);
resp.addCookie(cookie);
//显示主页面
resp.sendRedirect(req.getContextPath()+"/view/index.html");
/*
功能三:防止多点登录
使别人的session失效,即可实现让对方下线
当登陆成功时,将登陆的用户名作为key,当前用户的session作为value存储到ServletContext容器中
登录成功时,判断Servlet Context中 是否有登陆用户的key-value,
如果有,则将Servlet Context中存储的session失效,将登陆用户的session存到Servlet Context中
无论Servlet Context中是否有别人登录的session,都要将新登陆的用户的session存到其中,以便实现相互踢出功能
*/
/*
功能四:记住用户名密码
勾选框选中,写Cookie
*/
}
}
}
3.点击登录按钮,用输入的用户名和密码与数据库的用户名密码 进行校验
IndexServlet:
pw.println(" <form name='loginForm' method='post' action='"+request.getContextPath()+"/login'>");LoginServlet.java
List<Users> list = Dao.query(sql, Users.class,loginname,loginname+passwd);
if(list==null||list.size()==0){
//登录失败
//显示登录页面,给出提示
//调用 IndexServlet对象的service方法 无法实现
// 向IndexServlet进行跳转,需要传数据(登录失败的消息)
request.setAttribute("msg","登录失败!");
//请求转发跳转自动加上下文路径,因为调用的是request的方法
request.getRequestDispatcher("/index").forward(request,response);
}else{
//登录成功
//显示主页面
response.sendRedirect(request.getContextPath()+"/view/index.html");
}IndexServlet中获得request的Attribute值判断是否提示 登录失败
pw.println(" <script>");
if(request.getAttribute("msg")!=null){
pw.println("alert('"+request.getAttribute("msg")+"');");
}
二、实现防止非法登录功能
访问系统功能时,只能先从登录页面进行,登录成功后,再能使用其他的功能。
LoginServlet中
//登录成功,向session中存储Users对象
HttpSession session = request.getSession();
session.setAttribute("user",list.get(0));EmpServlet中
if(session.getAttribute("user")==null){
PrintWriter pw = response.getWriter();
pw.println("<script>");
pw.println("window.parent.location.href='"+request.getContextPath()+"/index'");
pw.println("</script>");
return;
//response.sendRedirect(request.getContextPath()+"/index");
}
三、实现防止多点登录功能
LoginServlet中:
else{
//登录成功,向session中存储Users对象
HttpSession session = request.getSession();
session.setAttribute("user",list.get(0));
//判断ServletContext中是否有登录的用户名key的value
ServletContext servletContext = this.getServletContext();
if(servletContext.getAttribute(loginname)!=null){
HttpSession otherSession = (HttpSession)servletContext.getAttribute(loginname);
//if(session!=otherSession)
if(!session.getId().equals(otherSession.getId()))
otherSession.invalidate();
}
//存入当前的Session对象
servletContext.setAttribute(loginname,session);
//显示主页面
response.sendRedirect(request.getContextPath()+"/view/index.html");
}
四、记住用户名密码功能
1. 如果勾选了 rememberMe的勾选框并登录成功时,向客户端发送用户名、密码、勾选框是否选中的Cookie;
pw.println("<td align='left'><input type='checkbox' "+("1".equals(rememberMe)?"checked":"")+" name='rememberMe' value='1'>记住用户名密码</td>");LoginServlet.java
else{
//登录成功,向session中存储Users对象
HttpSession session = request.getSession();
session.setAttribute("user",list.get(0));
//判断ServletContext中是否有登录的用户名key的value
ServletContext servletContext = this.getServletContext();
if(servletContext.getAttribute(loginname)!=null){
HttpSession otherSession =(HttpSession)servletContext.getAttribute(loginname);
//if(session!=otherSession)
if(!session.getId().equals(otherSession.getId()))
otherSession.invalidate();
}
//存入当前的Session对象
servletContext.setAttribute(loginname,session);
if(rememberMe!=null){
//向客户端响应Cookie
Cookie cookie = new Cookie("loginname",loginname);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
cookie = new Cookie("passwd",passwd);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
}
Cookie cookie = new Cookie("rememberMe",rememberMe);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
//显示主页面
response.sendRedirect(request.getContextPath()+"/view/index.html");
}
2. 进入到登录页面先访问IndexServlet,在IndexServlet中可以获得三个Cookie,如果勾选框是选中状态,就将 用户名、密码、勾选状态写到html中,IndexServlet发回浏览器
运行效果:
浏览器访问 http://localhost:8080/emp/index 为登录界面

2.勾选记住用户名密码,点击登录按钮,进入到主页

3.点击左侧目录中的“员工管理”

4. 点击新增按钮,填写信息,保存

5.点击“修改”,修改信息,保存

边栏推荐
- Realize the recognition and training of CNN images, and process the cifar10 data set and other methods through the tensorflow framework
- Which securities company has the lowest Commission for opening an account online? I want to open an account. Is it safe for the online account manager to open an account
- GoLand 2021.1.1: configure the multi line display of the tab of the open file
- 静态链表(数组的下标代替指针)
- 如何使用lxml判断网站公告是否更新
- Halcon combined with C # to detect surface defects -- Halcon routine autobahn
- Shell timing script, starting from 0, CSV format data is regularly imported into PostgreSQL database shell script example
- Depth and breadth first traversal of tree (regardless of binary tree)
- Uniapp tips - scrolling components
- 【被动收入如何挣个一百万】
猜你喜欢

全面发展数字经济主航道 和数集团积极推动UTONMOS数藏市场

3D vision - 2 Introduction to pose estimation - openpose includes installation, compilation and use (single frame, real-time video)

Go language unit test 4: go language uses gomonkey to test functions or methods

UiO-66-COOH装载苯达莫司汀|羟基磷灰石( HA) 包裹MIL-53(Fe)纳米粒子|装载黄芩苷锰基金属有机骨架材料

Go language web development series 28: solve cross domain access of CORS with gin contrib / CORS

Several common optimization methods matlab principle and depth analysis

【吉林大学】考研初试复试资料分享

Spring cup eight school league
![[技術發展-24]:現有物聯網通信技術特點](/img/f3/a219fe8e7438b8974d2226b4c3d4a4.png)
[技術發展-24]:現有物聯網通信技術特點

Unity embeddedbrowser browser plug-in event communication
随机推荐
logback日志的整理
Mysql:insert date:sql error [1292] [22001]: data truncation: incorrect date value:
Conversion function and explicit
MySQL data processing value addition, deletion and modification
Qt学习21 Qt 中的标准对话框(下)
GoLand 2021.2 configure go (go1.17.6)
Bidirectional linked list (we only need to pay attention to insert and delete functions)
解决MySql 1045 Access denied for user ‘root‘@‘localhost‘ (using password: YES)
Unable to stop it, domestic chips have made another breakthrough, and some links have reached 4nm
windos 创建cordova 提示 因为在此系统上禁止运行脚本
金属有机骨架MOFs装载非甾体类抗炎药物|ZIF-8包裹普鲁士蓝负载槲皮素(制备方法)
双向链表(我们只需要关注插入和删除函数)
Leetcode-1175.Prime Arrangements
Another industry has been broken by Chinese chips. No wonder the leading analog chip companies in the United States have cut prices and sold off
怎样删除对象的某个属性或⽅法
pytorch 载入历史模型时更换gpu卡号,map_location设置
Flutter dynamic | fair 2.5.0 new version features
Qt学习24 布局管理器(三)
金属有机骨架(MOFs)抗肿瘤药载体|PCN-223装载甲硝唑|UiO-66包载盐酸环丙沙星([email protected])
How to use lxml to judge whether the website announcement is updated