1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.concurrent;
17
18 import org.acegisecurity.AcegiMessageSource;
19 import org.acegisecurity.Authentication;
20 import org.acegisecurity.AuthenticationException;
21
22 import org.springframework.beans.factory.InitializingBean;
23
24 import org.springframework.context.MessageSource;
25 import org.springframework.context.MessageSourceAware;
26 import org.springframework.context.support.MessageSourceAccessor;
27
28 import org.springframework.util.Assert;
29
30
31
32
33
34
35
36
37
38 public class ConcurrentSessionControllerImpl implements ConcurrentSessionController, InitializingBean,
39 MessageSourceAware {
40
41
42 protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
43 private SessionRegistry sessionRegistry;
44 private boolean exceptionIfMaximumExceeded = false;
45 private int maximumSessions = 1;
46
47
48
49 public void afterPropertiesSet() throws Exception {
50 Assert.notNull(sessionRegistry, "SessionRegistry required");
51 Assert.isTrue(maximumSessions != 0,
52 "MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
53 Assert.notNull(this.messages, "A message source must be set");
54 }
55
56
57
58
59
60
61
62
63
64
65
66 protected void allowableSessionsExceeded(String sessionId, SessionInformation[] sessions, int allowableSessions,
67 SessionRegistry registry) {
68 if (exceptionIfMaximumExceeded || (sessions == null)) {
69 throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed",
70 new Object[] {new Integer(allowableSessions)},
71 "Maximum sessions of {0} for this principal exceeded"));
72 }
73
74
75 SessionInformation leastRecentlyUsed = null;
76
77 for (int i = 0; i < sessions.length; i++) {
78 if ((leastRecentlyUsed == null)
79 || sessions[i].getLastRequest().before(leastRecentlyUsed.getLastRequest())) {
80 leastRecentlyUsed = sessions[i];
81 }
82 }
83
84 leastRecentlyUsed.expireNow();
85 }
86
87 public void checkAuthenticationAllowed(Authentication request)
88 throws AuthenticationException {
89 Assert.notNull(request, "Authentication request cannot be null (violation of interface contract)");
90
91 Object principal = SessionRegistryUtils.obtainPrincipalFromAuthentication(request);
92 String sessionId = SessionRegistryUtils.obtainSessionIdFromAuthentication(request);
93
94 SessionInformation[] sessions = sessionRegistry.getAllSessions(principal, false);
95
96 int sessionCount = 0;
97
98 if (sessions != null) {
99 sessionCount = sessions.length;
100 }
101
102 int allowableSessions = getMaximumSessionsForThisUser(request);
103 Assert.isTrue(allowableSessions != 0, "getMaximumSessionsForThisUser() must return either -1 to allow "
104 + "unlimited logins, or a positive integer to specify a maximum");
105
106 if (sessionCount < allowableSessions) {
107
108 return;
109 } else if (allowableSessions == -1) {
110
111 return;
112 } else if (sessionCount == allowableSessions) {
113
114 for (int i = 0; i < sessionCount; i++) {
115 if (sessions[i].getSessionId().equals(sessionId)) {
116 return;
117 }
118 }
119 }
120
121 allowableSessionsExceeded(sessionId, sessions, allowableSessions, sessionRegistry);
122 }
123
124
125
126
127
128
129
130
131
132
133 protected int getMaximumSessionsForThisUser(Authentication authentication) {
134 return maximumSessions;
135 }
136
137 public void registerSuccessfulAuthentication(Authentication authentication) {
138 Assert.notNull(authentication, "Authentication cannot be null (violation of interface contract)");
139
140 Object principal = SessionRegistryUtils.obtainPrincipalFromAuthentication(authentication);
141 String sessionId = SessionRegistryUtils.obtainSessionIdFromAuthentication(authentication);
142
143 sessionRegistry.registerNewSession(sessionId, principal);
144 }
145
146 public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) {
147 this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
148 }
149
150 public void setMaximumSessions(int maximumSessions) {
151 this.maximumSessions = maximumSessions;
152 }
153
154 public void setMessageSource(MessageSource messageSource) {
155 this.messages = new MessageSourceAccessor(messageSource);
156 }
157
158 public void setSessionRegistry(SessionRegistry sessionRegistry) {
159 this.sessionRegistry = sessionRegistry;
160 }
161 }