Skip to content

Commit b7436c6

Browse files
committed
添加ui,踢出用户的拦截器
1 parent b1f94a1 commit b7436c6

File tree

354 files changed

+140401
-107
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

354 files changed

+140401
-107
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
<artifactId>tomcat-embed-jasper</artifactId>
3737
<scope>provided</scope>
3838
</dependency>
39+
40+
<!-- jstl标签 -->
41+
<dependency>
42+
<groupId>javax.servlet</groupId>
43+
<artifactId>jstl</artifactId>
44+
</dependency>
3945

4046
<dependency>
4147
<groupId>org.mybatis.spring.boot</groupId>

src/main/java/io/z77z/config/ShiroConfig.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import io.z77z.entity.SysPermissionInit;
44
import io.z77z.service.SysPermissionInitService;
55
import io.z77z.shiro.MyShiroRealm;
6+
import io.z77z.shiro.filter.KickoutSessionControlFilter;
67

78
import java.util.LinkedHashMap;
89
import java.util.List;
910
import java.util.Map;
1011

12+
import javax.servlet.Filter;
13+
1114
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
1215
import org.apache.shiro.web.mgt.CookieRememberMeManager;
1316
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
@@ -62,7 +65,13 @@ public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
6265
shiroFilterFactoryBean.setSuccessUrl("/index");
6366
// 未授权界面;
6467
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
65-
68+
69+
//自定义拦截器
70+
Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
71+
//限制同一帐号同时在线的个数。
72+
filtersMap.put("kickout", kickoutSessionControlFilter());
73+
shiroFilterFactoryBean.setFilters(filtersMap);
74+
6675
// 权限控制map.
6776
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
6877
// 配置不会被拦截的链接 顺序判断
@@ -94,7 +103,7 @@ public SecurityManager securityManager() {
94103
// 自定义缓存实现 使用redis
95104
securityManager.setCacheManager(cacheManager());
96105
// 自定义session管理 使用redis
97-
securityManager.setSessionManager(SessionManager());
106+
securityManager.setSessionManager(sessionManager());
98107
//注入记住我管理器;
99108
securityManager.setRememberMeManager(rememberMeManager());
100109
return securityManager;
@@ -149,7 +158,7 @@ public RedisSessionDAO redisSessionDAO() {
149158
/**
150159
* Session Manager
151160
*/
152-
public DefaultWebSessionManager SessionManager() {
161+
public DefaultWebSessionManager sessionManager() {
153162
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
154163
sessionManager.setSessionDAO(redisSessionDAO());
155164
//设置seesion有效时间
@@ -180,4 +189,25 @@ public CookieRememberMeManager rememberMeManager(){
180189
cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
181190
return cookieRememberMeManager;
182191
}
192+
193+
/**
194+
* 限制同一账号登录同时登录人数控制
195+
* @return
196+
*/
197+
public KickoutSessionControlFilter kickoutSessionControlFilter(){
198+
KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
199+
//使用cacheManager获取相应的cache来缓存用户登录的会话;用于保存用户—会话之间的关系的;
200+
//这里我们还是用之前shiro使用的redisManager()实现的cacheManager()缓存管理
201+
//也可以重新另写一个,重新配置缓存时间之类的自定义缓存属性
202+
kickoutSessionControlFilter.setCacheManager(cacheManager());
203+
//用于根据会话ID,获取会话进行踢出操作的;
204+
kickoutSessionControlFilter.setSessionManager(sessionManager());
205+
//是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;踢出顺序。
206+
kickoutSessionControlFilter.setKickoutAfter(false);
207+
//同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录;
208+
kickoutSessionControlFilter.setMaxSession(1);
209+
//被踢出后重定向到的地址;
210+
kickoutSessionControlFilter.setKickoutUrl("/kickout");
211+
return kickoutSessionControlFilter;
212+
}
183213
}

src/main/java/io/z77z/controller/LoginController.java renamed to src/main/java/io/z77z/controller/UserController.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,39 +28,56 @@
2828
* @date 创建时间:2017年2月10日 下午1:32:02
2929
*/
3030
@Controller
31-
public class LoginController {
31+
public class UserController {
3232

3333
@Autowired
3434
ShiroService shiroService;
3535

36+
//首页
3637
@RequestMapping(value="index")
3738
public String index() {
3839
return "index";
3940
}
40-
41+
42+
//登录
4143
@RequestMapping(value="login")
4244
public String login() {
4345
return "login";
4446
}
4547

46-
48+
//权限测试用
4749
@RequestMapping(value="add")
4850
public String add() {
4951
return "add";
5052
}
5153

54+
//未授权跳转的页面
5255
@RequestMapping(value="403")
5356
public String noPermissions() {
5457
return "403";
5558
}
5659

60+
//更新权限
5761
@RequestMapping(value="updatePermission")
5862
@ResponseBody
5963
public String updatePermission() {
6064
shiroService.updatePermission();
6165
return "true";
6266
}
6367

68+
//踢出用户
69+
@RequestMapping(value="kickouting")
70+
@ResponseBody
71+
public String kickouting() {
72+
73+
return "kickout";
74+
}
75+
76+
//被踢出后跳转的页面
77+
@RequestMapping(value="kickout")
78+
public String kickout() {
79+
return "kickout";
80+
}
6481

6582
/**
6683
* ajax登录请求
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package io.z77z.shiro.filter;
2+
3+
import org.apache.shiro.cache.Cache;
4+
import org.apache.shiro.cache.CacheManager;
5+
import org.apache.shiro.session.Session;
6+
import org.apache.shiro.session.mgt.DefaultSessionKey;
7+
import org.apache.shiro.session.mgt.SessionManager;
8+
import org.apache.shiro.subject.Subject;
9+
import org.apache.shiro.web.filter.AccessControlFilter;
10+
import org.apache.shiro.web.util.WebUtils;
11+
12+
import io.z77z.entity.SysUser;
13+
14+
import javax.servlet.ServletRequest;
15+
import javax.servlet.ServletResponse;
16+
import java.io.Serializable;
17+
import java.util.Deque;
18+
19+
/**
20+
* @author 作者 z77z
21+
* @date 创建时间:2017年3月5日 下午1:16:38
22+
* 1.读取当前登录用户名,获取在缓存中的sessionId队列
23+
* 2.判断队列的长度,大于最大登录限制的时候,按踢出规则
24+
* 将之前的sessionId中的session域中存入kickout:true,并更新队列缓存
25+
* 3.判断当前登录的session域中的kickout如果为true,
26+
* 想将其做退出登录处理,然后再重定向到踢出登录提示页面
27+
*/
28+
public class KickoutSessionControlFilter extends AccessControlFilter {
29+
30+
private String kickoutUrl; //踢出后到的地址
31+
private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
32+
private int maxSession = 1; //同一个帐号最大会话数 默认1
33+
34+
private SessionManager sessionManager;
35+
private Cache<String, Deque<Serializable>> cache;
36+
37+
public void setKickoutUrl(String kickoutUrl) {
38+
this.kickoutUrl = kickoutUrl;
39+
}
40+
41+
public void setKickoutAfter(boolean kickoutAfter) {
42+
this.kickoutAfter = kickoutAfter;
43+
}
44+
45+
public void setMaxSession(int maxSession) {
46+
this.maxSession = maxSession;
47+
}
48+
49+
public void setSessionManager(SessionManager sessionManager) {
50+
this.sessionManager = sessionManager;
51+
}
52+
//设置Cache的key的前缀
53+
public void setCacheManager(CacheManager cacheManager) {
54+
this.cache = cacheManager.getCache("shiro_redis_cache");
55+
}
56+
57+
@Override
58+
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
59+
return false;
60+
}
61+
62+
@Override
63+
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
64+
Subject subject = getSubject(request, response);
65+
if(!subject.isAuthenticated() && !subject.isRemembered()) {
66+
//如果没有登录,直接进行之后的流程
67+
return true;
68+
}
69+
70+
Session session = subject.getSession();
71+
SysUser user = (SysUser) subject.getPrincipal();
72+
String username = user.getNickname();
73+
Serializable sessionId = session.getId();
74+
75+
//读取缓存 没有就存入
76+
Deque<Serializable> deque = cache.get(username);
77+
78+
//如果队列里没有此sessionId,且用户没有被踢出;放入队列
79+
if(!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
80+
//将sessionId存入队列
81+
deque.push(sessionId);
82+
//将用户的sessionId队列缓存
83+
cache.put(username, deque);
84+
}
85+
86+
//如果队列里的sessionId数超出最大会话数,开始踢人
87+
while(deque.size() > maxSession) {
88+
Serializable kickoutSessionId = null;
89+
if(kickoutAfter) { //如果踢出后者
90+
kickoutSessionId = deque.removeFirst();
91+
} else { //否则踢出前者
92+
kickoutSessionId = deque.removeLast();
93+
}
94+
//踢出后再更新下缓存队列
95+
cache.put(username, deque);
96+
97+
98+
try {
99+
//获取被踢出的sessionId的session对象
100+
Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
101+
if(kickoutSession != null) {
102+
//设置会话的kickout属性表示踢出了
103+
kickoutSession.setAttribute("kickout", true);
104+
}
105+
} catch (Exception e) {//ignore exception
106+
}
107+
}
108+
109+
//如果被踢出了,直接退出,重定向到踢出后的地址
110+
if ((Boolean)session.getAttribute("kickout")!=null&&(Boolean)session.getAttribute("kickout") == true) {
111+
//会话被踢出了
112+
try {
113+
//退出登录
114+
subject.logout();
115+
} catch (Exception e) { //ignore
116+
}
117+
saveRequest(request);
118+
//重定向
119+
WebUtils.issueRedirect(request, response, kickoutUrl);
120+
return false;
121+
}
122+
return true;
123+
}
124+
}

src/main/webapp/WEB-INF/view/add.jsp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@
1515
<title>Insert title here</title>
1616
</head>
1717
<body>
18-
具有添加权限
18+
具有添加权限
19+
20+
<input type="button" id="updatePermission" value="更新链接权限" />
1921
</body>
22+
<script type="text/javascript">
23+
$("#updatePermission").click(function(){
24+
$.post("/updatePermission", {}, function(result) {
25+
if (result == "true") {
26+
alert("权限更新成功!!");
27+
}
28+
});
29+
});
30+
</script>
2031
</html>
Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,60 @@
1-
<%@ page language="java" contentType="text/html; charset=UTF-8"
2-
pageEncoding="UTF-8"%>
3-
<%
4-
String path = request.getContextPath();
5-
String basePath = request.getScheme() + "://"
6-
+ request.getServerName() + ":" + request.getServerPort()
7-
+ path;
8-
%>
9-
<!DOCTYPE html>
1+
<!DOCTYPE HTML>
2+
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
3+
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
104
<html>
11-
<head>
12-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
13-
<script type="text/javascript"
14-
src="<%=basePath%>/static/js/jquery-1.11.3.js"></script>
15-
<title>Insert title here</title>
16-
</head>
17-
<body>
18-
helloJsp
19-
<hr>${user}
20-
<input type="button" id="logout" value="退出登录" />
21-
<input type="button" id="updatePermission" value="更新链接权限" />
22-
<input type="button" id="add" value="访问权限页面" />
23-
</body>
24-
<script type="text/javascript">
25-
$("#logout").click(function(){
26-
location.href="/logout";
27-
});
28-
$("#updatePermission").click(function(){
29-
$.post("/updatePermission", {}, function(result) {
30-
if (result == "true") {
31-
alert("权限更新成功!!");
32-
}
33-
});
34-
});
35-
$("#add").click(function(){
36-
location.href="/add";
37-
});
38-
</script>
5+
<head>
6+
<title>z77z后台管理|首页</title>
7+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8+
<link href="<%=request.getContextPath()%>/static/assets/css/dpl-min.css" rel="stylesheet" type="text/css" />
9+
<link href="<%=request.getContextPath()%>/static/assets/css/bui-min.css" rel="stylesheet" type="text/css" />
10+
<link href="<%=request.getContextPath()%>/static/assets/css/main.css" rel="stylesheet" type="text/css" />
11+
</head>
12+
<body>
13+
<div class="header">
14+
<div class="dl-title">
15+
<a href="http://z77z.oschina.io/" title="个人博客地址" target="_blank">
16+
<span class="lp-title-port">z77z</span><span class="dl-title-text">后台管理系统</span>
17+
</a>
18+
</div>
19+
<div class="dl-log">欢迎您,<span class="dl-log-user">王二</span>
20+
<span class="admin">(管理员)</span>
21+
<a href="logout" title="退出系统" class="dl-log-quit">[退出]</a>
22+
</div>
23+
</div>
24+
<div class="content">
25+
<div class="dl-main-nav">
26+
<ul id="J_Nav" class="nav-list ks-clear">
27+
<li class="nav-item dl-selected"><div class="nav-item-inner nav-storage">首页</div></li>
28+
</ul>
29+
</div>
30+
<ul id="J_NavContent" class="dl-tab-conten">
31+
</ul>
32+
</div>
33+
<script type="text/javascript" src="<%=request.getContextPath()%>/static/assets/js/jquery-1.8.1.min.js"></script>
34+
<script type="text/javascript" src="<%=request.getContextPath()%>/static/assets/js/bui-min.js"></script>
35+
<script type="text/javascript" src="<%=request.getContextPath()%>/static/assets/js/config-min.js"></script>
36+
<script type="text/javascript" src="<%=request.getContextPath()%>/static/lib/layer/1.9.3/layer.js"></script>
37+
<script>
38+
//学生登录
39+
BUI.use('common/main',function(){
40+
var config = [{
41+
id:'system',
42+
menu:[{
43+
text:'系统管理',
44+
items:[
45+
{id:'yhgl',text:'用户管理',href:'/StuSystem/score/xsgrcjcx?studentId=' + '${userbean.userId}'},
46+
{id:'qxgl',text:'权限管理',href:'/StuSystem/score/scoreone?page=1&studentId=' + '${userbean.userId}' },
47+
{id:'jsgl',text:'角色管理',href:'/StuSystem/student/studentone?stuId=' + '${userbean.userId}' },
48+
{id:'csqxgl',text:'初始权限管理',href:'/StuSystem/user/dlmmxg'},
49+
{id:'zxyhgl',text:'在线用户管理',href:'/StuSystem/user/dlmmxg'},
50+
{id:'qxcsym',text:'权限测试页面',href:'/add'}
51+
]
52+
}]
53+
}];
54+
new PageUtil.MainPage({
55+
modulesConfig : config
56+
});
57+
});
58+
</script>
59+
</body>
3960
</html>

0 commit comments

Comments
 (0)