当前位置:网站首页>小项目(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.点击“修改”,修改信息,保存

边栏推荐
- Halcon combined with C # to detect surface defects -- Halcon routine autobahn
- Golang — template
- Spring cup eight school league
- 软件测试工作那么难找,只有外包offer,我该去么?
- 金属有机骨架MOFs装载非甾体类抗炎药物|ZIF-8包裹普鲁士蓝负载槲皮素(制备方法)
- Windos creates Cordova prompt because running scripts is prohibited on this system
- SQL Injection (POST/Search)
- [ACNOI2022]猜数
- Flutter动态化 | Fair 2.5.0 新版本特性
- GoLand 2021.1.1: configure the multi line display of the tab of the open file
猜你喜欢

SQL Injection (GET/Select)

Error running 'application' in idea running: the solution of command line is too long

Comprehensively develop the main channel of digital economy and digital group, and actively promote the utonmos digital Tibet market

Flutter dynamic | fair 2.5.0 new version features
[email protected]纳米颗粒)|纳米金属有机框架搭载雷帕霉素|科研试剂"/>金属有机骨架材料ZIF-8包载姜黄素([email protected]纳米颗粒)|纳米金属有机框架搭载雷帕霉素|科研试剂

可编程逻辑器件软件测试

Qt学习24 布局管理器(三)

Mobile phones and computers can be used, whole people, spoof code connections, "won't you Baidu for a while" teach you to use Baidu

Logback log sorting

Use and design of Muduo buffer class
随机推荐
Resource Cost Optimization Practice of R & D team
Shell timing script, starting from 0, CSV format data is regularly imported into PostgreSQL database shell script example
RichView TRVStyle ListStyle 列表样式(项目符号编号)
Screenshot of the operation steps of upload labs level 4-level 9
栈应用(平衡符)
树的深入和广度优先遍历(不考虑二叉树)
Static linked list (subscript of array instead of pointer)
太阳底下无新事,元宇宙能否更上层楼?
Stack application (balancer)
Go language web development series 29: Gin framework uses gin contrib / sessions library to manage sessions (based on cookies)
php 迷宫游戏
[combinatorics] permutation and combination (examples of combinatorial number of multiple sets | three counting models | selection problem | combinatorial problem of multiple sets | nonnegative intege
Mobile phones and computers can be used, whole people, spoof code connections, "won't you Baidu for a while" teach you to use Baidu
使用tensorflow进行完整的DNN深度神经网络CNN训练完成图片识别案例
GoLand 2021.1.1: configure the multi line display of the tab of the open file
Unable to stop it, domestic chips have made another breakthrough, and some links have reached 4nm
Leetcode-1175. Prime Arrangements
Qt学习25 布局管理器(四)
Sequence table (implemented in C language)
Depth and breadth first traversal of tree (regardless of binary tree)