引用:
知道了session混乱产生的原因之后,也就知道了问题的根源。同时也引出了很多的问题:
1、如何记录住在线人员(这里只有帐号的系统用户,不包括访客);
2、如何限制同一个帐号在同一时间段内只能够登陆一次系统?
3、如何限制不同的用户在同一台机器上登陆系统?
4、管理员如何踢人?
我们首先来分析上面的问题:
首先在服务器端当用户通过身份验证成功登陆系统之后,我们将此用户的信息记录住(OnLineUserManager.java),包括帐号、登陆日期、机器的IP地址、session的ID,session对象。(记住session的ID极其重要,因为服务器识别session是根据id,只要id相同,服务器就认为是同一个用户);
(上面解决了问题1)
这样当用户登陆系统的时候我们首先根据帐号判断用户是否登陆了,如果已经登陆,提示用户;(这样就解决了问题2)
如果未登陆,判断用户的session的id是否已经在用户的信息OnLineUserManager里面了,如果是提示用户
关闭当前窗口,重新点击IE打开一个新的浏览器窗口。(这样session就不会混乱了)。
如果要限制不同的用户在同一台机器上登陆系统?这个就要根据IP地址来判断了。如果OnLineUserManager中
有通过这个机器登陆系统的用户,那么就提示用户同一台机器只能够一个帐号登陆;
注意:如果用户使用了代理服务器,那么此方法失效。这个方法适用于管理规范的用户,客户在局域网内使用,每个客户有固定的ip。)
问题4如何踢人?你想想OnLineUserManager中记录了用户session对象,只要根据用户的帐号找到对应的
session对象,然后session.invalidate();这样就可以彻底的将捣乱的人提出系统了。
===============需要注意的是OnLineUserManager必须是线程安全的=我的实现如下==============
1. package com.work.qxgl.login;
2.
3.
4.
5. import java.util.Vector;
6.
7.
8.
9. import org.apache.commons.logging.Log;
10.
11. import org.apache.commons.logging.LogFactory;
12.
13.
14.
15. import com.work.util.DateUtil;
16.
17.
18.
19. /**
20.
21. * 统计在线用户数。前提是登录的时候限制一个用户只能够在系统中登录一次。 有了这个功能,管理员就可以管理在线用户,如果谁不服从管理,就可以从系统中踢出去。
22.
23. * TODO 将jsp放到WEB-INF后面,然后所有的URL必须通过struts的action调用。 使用拦截器Interceptor来实现权限的控制!
24.
25. * 或者通过web中的Filter来实现权限控制! 实现权限管理系统日志的记录!
26.
27. *
28.
29. * @author wangmingjie
30.
31. *
32.
33. */
34.
35. public class OnLineUserManager {
36.
37. private static Log log = LogFactory.getLog(OnLineUserManager.class);
38.
39. private Vector<OnLineUser> users = null;
40.
41.
42.
43.
44.
45. private OnLineUserManager() {
46.
47. new Vector<OnLineUser>();//在构造函数中初始化
48.
49. }
50.
51.
52.
53. static class SingletonHolder {
54.
55. static OnLineUserManager instance = new OnLineUserManager();
56.
57. }
58.
59.
60.
61. /**
62.
63. * 单例模式。这样简单而且能够保证线程安全。
64.
65. *
66.
67. * @return
68.
69. */
70.
71. public static OnLineUserManager getInstance() {
72.
73. return SingletonHolder.instance;
74.
75. }
76.
77.
78.
79. /**
80.
81. * 获取到登录用户的数量。
82.
83. *
84.
85. * @return
86.
87. */
88.
89. public synchronized int getCount() {
90.
91. users.trimToSize();
92.
93. return users.capacity();
94.
95. }
96.
97.
98.
99. /**
100.
101. * 通过用户帐号判断该用户是否存在! 必须保证是线程安全的。
102.
103. *
104.
105. * @param userAccount
106.
107. * @return
108.
109. */
110.
111. public synchronized boolean existUser(String userAccount) {
112.
113. users.trimToSize();
114.
115. boolean existUser = false;
116.
117. for (int i = 0; i < users.capacity(); i++) {
118.
119. if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {
120.
121. true;
122.
123. break;
124.
125. }
126.
127. }
128.
129. return existUser;
130.
131. }
132.
133.
134.
135. /**
136.
137. * @param sessionid
138.
139. * @return
140.
141. */
142.
143. public synchronized boolean existSession(String sessionid) {
144.
145. users.trimToSize();
146.
147. boolean existUser = false;
148.
149. for (int i = 0; i < users.capacity(); i++) {
150.
151. if (sessionid.equals(((OnLineUser) users.get(i)).getSessionId())) {
152.
153. true;
154.
155. break;
156.
157. }
158.
159. }
160.
161. return existUser;
162.
163. }
164.
165.
166.
167.
168.
169. /**
170.
171. * 删除用户
172.
173. *
174.
175. * @param userAccount
176.
177. * @return
178.
179. */
180.
181. public synchronized boolean deleteUser(String userAccount) {
182.
183. users.trimToSize();
184.
185. if (existUser(userAccount)) {
186.
187. int currUserIndex = -1;
188.
189. for (int i = 0; i < users.capacity(); i++) {
190.
191. if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {
192.
193. currUserIndex = i;
194.
195. break;
196.
197. }
198.
199. }
200.
201. if (currUserIndex != -1) {
202.
203. users.remove(currUserIndex);
204.
205. users.trimToSize();
206.
207. "用户" + userAccount + "退出系统"
208.
209. + DateUtil.getCurrentDateTime());
210.
211. "在线用户数为:" + getCount());
212.
213. return true;
214.
215. }
216.
217. }
218.
219. return false;
220.
221. }
222.
223.
224.
225. /**
226.
227. * 根据用户帐号,获取在线用户信息
228.
229. * @param userAccount
230.
231. * @return
232.
233. */
234.
235. public synchronized OnLineUser getUser(String userAccount) {
236.
237. users.trimToSize();
238.
239. if (existUser(userAccount)) {
240.
241. int currUserIndex = -1;
242.
243. for (int i = 0; i < users.capacity(); i++) {
244.
245. if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {
246.
247. currUserIndex = i;
248.
249. break;
250.
251. }
252.
253. }
254.
255. if (currUserIndex != -1) {
256.
257. return users.get(currUserIndex);
258.
259. }
260.
261. }
262.
263. return null;
264.
265. }
266.
267.
268.
269. /**
270.
271. * 获取到在线用户的信息。
272.
273. *
274.
275. * @return
276.
277. */
278.
279. public synchronized Vector<OnLineUser> getOnLineUser() {
280.
281. return users;
282.
283. }
284.
285.
286.
287. public synchronized void addUser(OnLineUser onLineUser) {
288.
289. users.trimToSize();
290.
291. if (!existUser(onLineUser.getUserAccount())) {
292.
293. users.add(onLineUser);
294.
295. "/t登录到系统/t" + DateUtil.getCurrentDateTime());
296.
297. // 通过request才能够获取到用户的ip等信息
298.
299. else {
300.
301. "已经存在");
302.
303. }
304.
305. "在线用户数为:" + getCount());
306.
307. }
308.
309.
310.
311. }
==================OnLineUser.java============================
1. package com.work.qxgl.login;
2.
3.
4.
5. import java.io.Serializable;
6.
7.
8.
9. import javax.servlet.http.HttpSession;
10.
11.
12.
13. /**
14.
15. * @author wangmingjie
16.
17. * @date 2008-6-30下午04:56:37
18.
19. */
20.
21. public class OnLineUser implements Serializable {
22.
23.
24.
25. /**
26.
27. *
28.
29. */
30.
31. private static final long serialVersionUID = 5461473880667036331L;
32.
33.
34.
35. private String userId; //用户id
36.
37. private String userAccount; //用户帐号
38.
39. private String userName; //用户名称
40.
41.
42.
43. private String loginTime; //登陆时间戳
44.
45.
46.
47. private String sessionId; //session的ID
48.
49. private String userIp ;//ip地址
50.
51.
52.
53. private HttpSession session; //记住session对象,测试能否用来将人员踢出系统
54.
55.
56.
57.
58.
59. public String getUserId() {
60.
61. return userId;
62.
63. }
64.
65.
66.
67. public void setUserId(String userId) {
68.
69. this.userId = userId;
70.
71. }
72.
73.
74.
75. public String getUserAccount() {
76.
77. return userAccount;
78.
79. }
80.
81.
82.
83. public void setUserAccount(String userAccount) {
84.
85. this.userAccount = userAccount;
86.
87. }
88.
89.
90.
91. public String getUserName() {
92.
93. return userName;
94.
95. }
96.
97.
98.
99. public void setUserName(String userName) {
100.
101. this.userName = userName;
102.
103. }
104.
105.
106.
107. public String getSessionId() {
108.
109. return sessionId;
110.
111. }
112.
113.
114.
115. public void setSessionId(String sessionId) {
116.
117. this.sessionId = sessionId;
118.
119. }
120.
121.
122.
123. public String getUserIp() {
124.
125. return userIp;
126.
127. }
128.
129.
130.
131. public void setUserIp(String userIp) {
132.
133. this.userIp = userIp;
134.
135. }
136.
137.
138.
139. public HttpSession getSession() {
140.
141. return session;
142.
143. }
144.
145.
146.
147. public void setSession(HttpSession session) {
148.
149. this.session = session;
150.
151. }
152.
153.
154.
155. public String getLoginTime() {
156.
157. return loginTime;
158.
159. }
160.
161.
162.
163. public void setLoginTime(String loginTime) {
164.
165. this.loginTime = loginTime;
166.
167. }
168.
169. public String toString(){
170.
171. return "OnLineUser{userId="+userId+",userAccount="+userAccount
172.
173. ",userName"+userName+",loginTime="+loginTime+",userIp="+userIp+",sessionId="+sessionId+"}";
174.
175. }
176.
177.
178.
179. //===============下面的数据只有在系统登陆日期中记录==================================
180.
181. // private String logoutTime;//退出时间戳;
182.
183. // private String logoutType;//退出方式 “session超时退出”;“1主动退出”
184.
185. // private String lastAccessedTime;// 最后访问时间
186.
187.
188.
189. }