Java web实现账号单一登录,防止同一账号重复登录(踢人效果)
作者:老孙的博客 发布时间:2021-05-24 13:26:09
实现了Java web开发账号单一登录的功能,防止同一账号重复登录,后面登录的踢掉前面登录的,使用过滤器Filter实现的。可以先下载项目下来测试下效果。
有博客写的是没个一段时间(比如500ms)读取后台的session进行验证,这种方法除了会占用资源,还会出现访问session(请求1)的返回值和自己提交请求(请求2)的返回值发生冲突。比如请求1先提交,此时请求1的返回值还未返回到前端,请求2提交,实际上我们想要的是请求1的返回值先返回,然后再返回请求2的返回值,但是这不是肯定会发生的,ajax的机制所导致的,具体什么原因没查到。总之出现了请求2先返回了返回值,这时候请求1接收到了请求2的返回值,妥妥的前端出现错误,但是后台却是成功的。
下面进入主题
工程下载链接:链接: https://pan.baidu.com/s/1Rp09wv7hTJLqx9DiQ_KSeA 提取码: xyym
其中:jquery-1.11.3.js是网上的工具
建立两个简单的界面
登录界面:为了简单没有设置密码,直接输入账号点击登录就行
// index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>" rel="external nofollow" rel="external nofollow" >
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css" rel="external nofollow" rel="external nofollow" >
-->
</head>
<body>
<input id="username" name="username" type="text">
<!-- <a href="singlecount.jsp" rel="external nofollow" target="_self"> -->
<button id="btnlogin" name="btnlogin">登录</button><!-- </a> -->
<!-- 引入jQuery -->
<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
<script type="text/javascript" src="js/jsSubmit.js"></script>
</body>
</html>
主页面:简单的一个提交按钮
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>" rel="external nofollow" rel="external nofollow" >
<title>My JSP 'SingleCount.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css" rel="external nofollow" rel="external nofollow" >
-->
</head>
<body>
已登录. <br>
<button id="btnsubmit" name="submit">提交</button>
<!-- 引入jQuery -->
<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
<script type="text/javascript" src="js/jsSubmit.js"></script>
</body>
</html>
写ajax,向后台提交请求
// jsSubmit.js
$(document).ready(function() {
// 登录按钮
$("#btnlogin").click(function() {
//data,dataType,type,url
$.ajax({
url: 'LoginServlet?method=login',
type: 'post',
data: {username: $("input[name='username']").val()}, // 将用户名传给servlet
//dataType:'json',
success: function(msg) { // msg为从servlet接收到的返回值
if (msg == 1) { // 接收到后台数据为1,正常登录
window.location.href = "singlecount.jsp";
}
},
error:function(){
window.alert("错误!");
}
});
});
// 提交按钮
$("#btnsubmit").click(function() {
//data,dataType,type,url
$.ajax({
url: 'SubmitServlet?method=submit',
type: 'post',
//dataType:'json',
success: function(msg) { // msg为从servlet接收到的返回值
if (msg >= 1) { // 正常
window.alert("提交总数" + msg);
}
},
error:function(jqXHR){
if(jqXHR.status == 900){ // 900状态码
window.alert("登录状态失效,请重新登录!");
window.location.href = "/OneLogin";
}
}
});
});
});
servlet
这部分有点长,其实主要内容直接看doPost方法就可以了。
// LoginServlet
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletConfig;
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;
@SuppressWarnings("serial")
//注解表明什么样的情况下可以访问该内容
@WebServlet(urlPatterns={"/LoginServlet"})
public class LoginServlet extends HttpServlet {
private PrintWriter out; // 输出流
private String user;
private String method;
private HttpSession session;
// 建立一个Map存储session信息,key-用户名,value-session
public static Map<String, HttpSession> user_Session = new HashMap<String, HttpSession>();
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
// 在这里实现方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/html");
//语言编码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
out = resp.getWriter();
user = req.getParameter("username"); // 获取index界面username的内容
method = req.getParameter("method"); // 获取方法名
session = req.getSession(); // 获取session
switch (method) {
case "login":
mLogin();
break;
default:
break;
}
out.flush();
out.close();
}
private void mLogin() { // 按登录按钮调用的方法
// TODO Auto-generated method stub
removeUser(user);
session.setAttribute("name", user);
user_Session.put(user, session); // 新增或覆盖session
System.out.println(user_Session);
out.println(1); // 返回值1,随意选个值,和前端对应就可以
}
/**
* 判断是否有重复用户,
* 若出现重复用户,踢掉前面登录的用户,即删除其session
*/
private void removeUser(String user) {
if(user_Session.containsKey(user))
user_Session.get(user).invalidate();
}
}
// SubmitServlet
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
//注解表明什么样的情况下可以访问该内容 会在js和web.xml中使用
@WebServlet(urlPatterns={"/SubmitServlet"})
public class SubmitServlet extends HttpServlet {
private PrintWriter out; // 输出流
private String method;
private int number = 0; // 计数
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
// 在这里实现方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/html");
//语言编码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
out = resp.getWriter();
method = req.getParameter("method"); // 获取方法名
switch (method) {
case "submit":
mSubmit();
break;
default:
break;
}
out.flush();
out.close();
}
private void mSubmit() { // 按提交按钮调用的方法
// TODO Auto-generated method stub
number++;
out.println(number);
}
}
过滤器
过滤器的原理这里就不说了,简单来说就是请求要先经过过滤器才能到达servlet,也就是说如果请求不满足要求就无法通过过滤器,这里的要求是要有session。
package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebFilter("/SessionFilter")
public class SessionFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
String strURL = request.getRequestURL().toString(); // 获取请求路径
// System.out.println(strURL);
// 只过滤来自SubmitServlet请求和singlecount.jsp的加载,可以设置成自己想过滤的
// 需要在web.xml中添加<filter>
if(strURL.indexOf("SubmitServlet") != -1 || strURL.indexOf("singlecount.jsp") != -1){
if(request.getSession().getAttribute("name") == null){
request.getSession().invalidate();
response.sendError(900, "登录失效,请重新登录!"); // 自定义状态码,session失效
// 900 到ajax的error中处理
return;
}
else {
arg2.doFilter(arg0, arg1);
}
}
else {
arg2.doFilter(arg0, arg1);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>OneLogin</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>filter.SessionFilter</filter-name>
<filter-class>filter.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter.SessionFilter</filter-name>
<url-pattern>/singlecount.jsp</url-pattern> <!-- 给界面添加过滤器 -->
</filter-mapping>
<filter-mapping>
<filter-name>filter.SessionFilter</filter-name>
<url-pattern>/SubmitServlet</url-pattern> <!-- 给servlet添加过滤器 -->
</filter-mapping>
</web-app>
实现效果
可以使用两个不同的浏览器当两个客户端,或者电脑多就用多台电脑。
相同账号登录时,前面账号再点提交请求就会给出提示,跳转到登录界面
未登录直接进入:http://localhost:8080/OneLogin/singlecount.jsp
如果也想实现跳转效果,在jsSubmit.js的$(document).ready(function() {…});
前面加入是否有session的判断,没有就给出提示,跳转到登录界面。
总结
以上所述是小编给大家介绍的Java web实现账号单一登录,防止同一账号重复登录,网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://blog.csdn.net/qq_34826261/article/details/102667780
猜你喜欢
- 前言今天遇到一个问题,我们有个ip.dat二进制文件,通过里面内容可以解析ip所在的地域信息,本地单元测试都是OK的,部署到测试环境后,发现
- 前言Spring框架的 validator 组件,是个辅助组件,在进行数据的完整性和有效性非常有用,通过定义一个某个验证器,即可在其它需要的
- engine的实现结构elasticsearch对于索引中的数据操作如读写get等接口都封装在engine中,同时engine还封装了索引的
- 1 前言许多语言,例如 Perl ,Python 和 Ruby ,都有集合的本地支持。有些语言(例如Python)甚至将基本集合组件(列表,
- 使用java来实现一个简单的计算器,供大家参考,具体内容如下最近使用java制作了一个计算器,菜单栏里的功能没有实现,只是写一个版式,仅仅实
- 本文实例讲述了Java面向接口编程之简单工厂模式。分享给大家供大家参考,具体如下:一 代码interface Output{ /
- 什么是ServletContext?根据字面意思即Servlet上下文服务器会为每一个工程创建一个对象,这个对象就是ServletConte
- 本文实例为大家分享了java实现简单发红包的具体代码,供大家参考,具体内容如下这个案例是普通红包,均分的,不是拼手气红包。package n
- 当前,JVM生态圈主要的三大构建工具:Apache Ant(带着Ivy)MavenGradle对于初学者,Ant是最清晰的,只要读懂Xml配
- 相信大家最关心的肯定不是什么一大堆的破理论,然后还似懂非懂的,最关心得莫过于服务之间的参数传递,数据获取。Ok,今天就告诉大家三种微服务之间
- 堆排序基本介绍1、堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),
- @RequestBody,@RequestParam和@Param区别@Param@Param是mybatis中的注解,用注解来简化xml配
- 前言借用《Effactive Java》这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点
- 本文实例讲述了java在网页上面抓取邮件地址的方法。分享给大家供大家参考。具体实现方法如下:import java.io.BufferedR
- 中断线程线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡、还是等
- 递归算法设计的基本思想是:对于一个复杂的问题,把原问题分解为若干个相对简单类同的子问题,继续下去直到子问题简单到能够直接求解,也就是说到了递
- 这篇文章主要介绍了Spring如何使用注解的方式创建bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- 昨天给各位总结了本人学习springboot整合mybatis第一阶段的一些学习心得和源码,主要就算是敲了一下SpringBoot的门儿,希
- public Bitmap CopyBitmap(Bitmap source){ int depth =
- 本文实例讲述了Java使用Jdbc连接Oracle执行简单查询操作。分享给大家供大家参考,具体如下:Java Jdbc 连接 Oracle