JSEC-37 - architectural preparation to enable easy assumed identity support. Need to vet modifications before they can be verified as the final solution.
git-svn-id: https://svn.apache.org/repos/asf/incubator/jsecurity/trunk@734355 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/org/jsecurity/mgt/DefaultSecurityManager.java b/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
index c9adf89..5487675 100644
--- a/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
+++ b/core/src/org/jsecurity/mgt/DefaultSecurityManager.java
@@ -26,10 +26,12 @@
import org.jsecurity.realm.Realm;
import org.jsecurity.session.InvalidSessionException;
import org.jsecurity.session.Session;
-import org.jsecurity.subject.*;
+import org.jsecurity.subject.AbstractRememberMeManager;
+import org.jsecurity.subject.PrincipalCollection;
+import org.jsecurity.subject.RememberMeManager;
+import org.jsecurity.subject.Subject;
import org.jsecurity.util.ThreadContext;
-import java.net.InetAddress;
import java.util.Collection;
/**
@@ -75,10 +77,16 @@
protected RememberMeManager rememberMeManager;
+ protected SubjectFactory subjectFactory;
+
+ protected SubjectBinder subjectBinder;
+
/**
* Default no-arg constructor.
*/
public DefaultSecurityManager() {
+ setSubjectBinder(new SessionSubjectBinder());
+ setSubjectFactory(new DefaultSubjectFactory(this));
}
/**
@@ -87,6 +95,7 @@
* @param singleRealm the single realm used by this SecurityManager.
*/
public DefaultSecurityManager(Realm singleRealm) {
+ this();
setRealm(singleRealm);
}
@@ -96,9 +105,26 @@
* @param realms the realm instances backing this SecurityManager.
*/
public DefaultSecurityManager(Collection<Realm> realms) {
+ this();
setRealms(realms);
}
+ public SubjectFactory getSubjectFactory() {
+ return subjectFactory;
+ }
+
+ public void setSubjectFactory(SubjectFactory subjectFactory) {
+ this.subjectFactory = subjectFactory;
+ }
+
+ public SubjectBinder getSubjectBinder() {
+ return subjectBinder;
+ }
+
+ public void setSubjectBinder(SubjectBinder subjectBinder) {
+ this.subjectBinder = subjectBinder;
+ }
+
public RememberMeManager getRememberMeManager() {
return rememberMeManager;
}
@@ -158,34 +184,9 @@
getRememberMeManagerForCipherAttributes().setDecryptionCipherKeyBase64(base64);
}
- private void assertPrincipals(AuthenticationInfo info) {
- PrincipalCollection principals = info.getPrincipals();
- if (principals == null || principals.isEmpty()) {
- String msg = "Authentication info returned from Authenticator must have non null and non empty principals.";
- throw new IllegalArgumentException(msg);
- }
- }
-
protected Subject createSubject() {
PrincipalCollection principals = getRememberedIdentity();
- return createSubject(principals);
- }
-
- protected Subject createSubject(PrincipalCollection subjectPrincipals) {
- return createSubject(subjectPrincipals, null);
- }
-
- protected Subject createSubject(PrincipalCollection principals, Session existing) {
- return createSubject(principals, existing, false);
- }
-
- protected Subject createSubject(PrincipalCollection principals, Session existing, boolean authenticated) {
- return createSubject(principals, existing, authenticated, null);
- }
-
- protected Subject createSubject(PrincipalCollection principals, Session existing,
- boolean authenticated, InetAddress inetAddress) {
- return new DelegatingSubject(principals, authenticated, inetAddress, existing, this);
+ return getSubjectFactory().createSubject(principals, null, false, null);
}
/**
@@ -197,25 +198,7 @@
* authenticated user.
*/
protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info) {
- assertPrincipals(info);
-
- //get any existing session that may exist - we don't want to lose it:
- Subject subject = getSubject(false);
- Session session = null;
- if (subject != null) {
- session = subject.getSession(false);
- }
-
- InetAddress authcSourceIP = null;
- if (token instanceof InetAuthenticationToken) {
- authcSourceIP = ((InetAuthenticationToken) token).getInetAddress();
- }
- if (authcSourceIP == null) {
- //try the thread local:
- authcSourceIP = ThreadContext.getInetAddress();
- }
-
- return createSubject(info.getPrincipals(), session, true, authcSourceIP);
+ return getSubjectFactory().createSubject(token, info, getSubject(false));
}
/**
@@ -228,10 +211,7 @@
* for later use.
*/
protected void bind(Subject subject) {
- if (log.isTraceEnabled()) {
- log.trace("Binding Subject [" + subject + "] to a thread local...");
- }
- ThreadContext.bind(subject);
+ getSubjectBinder().bind(subject);
}
private void assertCreation(Subject subject) throws IllegalStateException {
@@ -358,16 +338,16 @@
Subject subject = getSubject(false);
if (subject != null) {
try {
- stopSession(subject);
- } catch (Exception e) {
- if (log.isDebugEnabled()) {
- String msg = "Unable to cleanly stop Session for Subject [" + subject.getPrincipal() + "] " +
- "Ignoring (logging out).";
- log.debug(msg, e);
- }
- }
- try {
unbind(subject);
+ try {
+ stopSession(subject);
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ String msg = "Unable to cleanly stop Session for Subject [" + subject.getPrincipal() + "] " +
+ "Ignoring (logging out).";
+ log.debug(msg, e);
+ }
+ }
} catch (Exception e) {
if (log.isDebugEnabled()) {
String msg = "Unable to cleanly unbind Subject. Ignoring (logging out).";
@@ -394,7 +374,7 @@
}
protected void unbind(Subject subject) {
- ThreadContext.unbindSubject();
+ getSubjectBinder().unbind(subject);
}
protected PrincipalCollection getRememberedIdentity() {
@@ -414,7 +394,7 @@
}
protected Subject getSubject(boolean create) {
- Subject subject = ThreadContext.getSubject();
+ Subject subject = getSubjectBinder().getSubject();
if (subject == null && create) {
subject = createSubject();
bind(subject);
diff --git a/core/src/org/jsecurity/mgt/DefaultSubjectFactory.java b/core/src/org/jsecurity/mgt/DefaultSubjectFactory.java
new file mode 100644
index 0000000..a7f612c
--- /dev/null
+++ b/core/src/org/jsecurity/mgt/DefaultSubjectFactory.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jsecurity.mgt;
+
+import org.jsecurity.authc.AuthenticationInfo;
+import org.jsecurity.authc.AuthenticationToken;
+import org.jsecurity.authc.InetAuthenticationToken;
+import org.jsecurity.session.Session;
+import org.jsecurity.subject.DelegatingSubject;
+import org.jsecurity.subject.PrincipalCollection;
+import org.jsecurity.subject.Subject;
+import org.jsecurity.util.ThreadContext;
+
+import java.net.InetAddress;
+
+/**
+ * TODO - Class JavaDoc
+ *
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public class DefaultSubjectFactory implements SubjectFactory {
+
+ private SecurityManager securityManager;
+
+ public DefaultSubjectFactory() {
+ }
+
+ public DefaultSubjectFactory(SecurityManager securityManager) {
+ setSecurityManager(securityManager);
+ }
+
+ public SecurityManager getSecurityManager() {
+ return securityManager;
+ }
+
+ public void setSecurityManager(SecurityManager securityManager) {
+ this.securityManager = securityManager;
+ }
+
+ public Subject createSubject(PrincipalCollection principals, Session existing,
+ boolean authenticated, InetAddress inetAddress) {
+ return new DelegatingSubject(principals, authenticated, inetAddress, existing, getSecurityManager());
+ }
+
+ private void assertPrincipals(AuthenticationInfo info) {
+ PrincipalCollection principals = info.getPrincipals();
+ if (principals == null || principals.isEmpty()) {
+ String msg = "AuthenticationInfo must have non null and non empty principals.";
+ throw new IllegalArgumentException(msg);
+ }
+ }
+
+ /**
+ * Creates a <tt>Subject</tt> instance for the user represented by the given method arguments.
+ *
+ * @param token the <tt>AuthenticationToken</tt> submitted for the successful authentication.
+ * @param info the <tt>AuthenticationInfo</tt> of a newly authenticated user.
+ * @return the <tt>Subject</tt> instance that represents the user and session data for the newly
+ * authenticated user.
+ */
+ public Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing) {
+ assertPrincipals(info);
+
+ //get any existing session that may exist - we don't want to lose it:
+ Session session = null;
+ if (existing != null) {
+ session = existing.getSession(false);
+ }
+
+ InetAddress authcSourceIP = null;
+ if (token instanceof InetAuthenticationToken) {
+ authcSourceIP = ((InetAuthenticationToken) token).getInetAddress();
+ }
+ if (authcSourceIP == null) {
+ //try the thread local:
+ authcSourceIP = ThreadContext.getInetAddress();
+ }
+
+ return createSubject(info.getPrincipals(), session, true, authcSourceIP);
+ }
+}
diff --git a/core/src/org/jsecurity/mgt/SessionSubjectBinder.java b/core/src/org/jsecurity/mgt/SessionSubjectBinder.java
new file mode 100644
index 0000000..0597541
--- /dev/null
+++ b/core/src/org/jsecurity/mgt/SessionSubjectBinder.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jsecurity.mgt;
+
+import org.jsecurity.session.Session;
+import org.jsecurity.subject.PrincipalCollection;
+import org.jsecurity.subject.Subject;
+
+/**
+ * Binds the Subject to the accessible Session in addition to the ThreadContext.
+ *
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public class SessionSubjectBinder extends ThreadContextSubjectBinder {
+
+ /**
+ * The key that is used to store subject principals in the session.
+ */
+ public static final String PRINCIPALS_SESSION_KEY = SessionSubjectBinder.class.getName() + "_PRINCIPALS_SESSION_KEY";
+
+ /**
+ * The key that is used to store whether or not the user is authenticated in the session.
+ */
+ public static final String AUTHENTICATED_SESSION_KEY = SessionSubjectBinder.class.getName() + "_AUTHENTICATED_SESSION_KEY";
+
+ @Override
+ public void bind(Subject subject) {
+ bindToSession(subject);
+ super.bind(subject);
+ }
+
+ protected void bindToSession(Subject subject) {
+ PrincipalCollection principals = subject.getPrincipals();
+ if (principals != null && !principals.isEmpty()) {
+ Session session = subject.getSession();
+ session.setAttribute(PRINCIPALS_SESSION_KEY, principals);
+ } else {
+ Session session = subject.getSession(false);
+ if (session != null) {
+ session.removeAttribute(PRINCIPALS_SESSION_KEY);
+ }
+ }
+
+ if (subject.isAuthenticated()) {
+ Session session = subject.getSession();
+ session.setAttribute(AUTHENTICATED_SESSION_KEY, subject.isAuthenticated());
+ } else {
+ Session session = subject.getSession(false);
+ if (session != null) {
+ session.removeAttribute(AUTHENTICATED_SESSION_KEY);
+ }
+ }
+ }
+
+ @Override
+ public void unbind(Subject subject) {
+ Session session = subject.getSession(false);
+ if (session != null) {
+ session.removeAttribute(PRINCIPALS_SESSION_KEY);
+ session.removeAttribute(AUTHENTICATED_SESSION_KEY);
+ }
+ super.unbind(subject);
+ }
+}
diff --git a/core/src/org/jsecurity/mgt/SubjectBinder.java b/core/src/org/jsecurity/mgt/SubjectBinder.java
new file mode 100644
index 0000000..d06b021
--- /dev/null
+++ b/core/src/org/jsecurity/mgt/SubjectBinder.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jsecurity.mgt;
+
+import org.jsecurity.subject.Subject;
+
+/**
+ * TODO - Class JavaDoc
+ *
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public interface SubjectBinder {
+
+ Subject getSubject();
+
+ void bind(Subject subject);
+
+ void unbind(Subject subject);
+}
diff --git a/core/src/org/jsecurity/mgt/SubjectFactory.java b/core/src/org/jsecurity/mgt/SubjectFactory.java
new file mode 100644
index 0000000..51c8712
--- /dev/null
+++ b/core/src/org/jsecurity/mgt/SubjectFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jsecurity.mgt;
+
+import org.jsecurity.authc.AuthenticationInfo;
+import org.jsecurity.authc.AuthenticationToken;
+import org.jsecurity.session.Session;
+import org.jsecurity.subject.PrincipalCollection;
+import org.jsecurity.subject.Subject;
+
+import java.net.InetAddress;
+
+/**
+ * TODO - Class JavaDoc
+ *
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public interface SubjectFactory {
+
+ Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing);
+
+ Subject createSubject(PrincipalCollection principals, Session existing,
+ boolean authenticated, InetAddress originatingHost);
+
+}
diff --git a/core/src/org/jsecurity/mgt/ThreadContextSubjectBinder.java b/core/src/org/jsecurity/mgt/ThreadContextSubjectBinder.java
new file mode 100644
index 0000000..1fd310a
--- /dev/null
+++ b/core/src/org/jsecurity/mgt/ThreadContextSubjectBinder.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jsecurity.mgt;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jsecurity.subject.Subject;
+import org.jsecurity.util.ThreadContext;
+
+/**
+ * TODO - Class JavaDoc
+ *
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public class ThreadContextSubjectBinder implements SubjectBinder {
+
+ private static final Log log = LogFactory.getLog(ThreadContextSubjectBinder.class);
+
+ public Subject getSubject() {
+ return ThreadContext.getSubject();
+ }
+
+ public void bind(Subject subject) {
+ if (log.isTraceEnabled()) {
+ log.trace("Binding Subject [" + subject + "] to a thread local...");
+ }
+ ThreadContext.bind(subject);
+ }
+
+ public void unbind(Subject subject) {
+ ThreadContext.unbindSubject();
+ }
+}
diff --git a/web/src/org/jsecurity/web/DefaultWebSecurityManager.java b/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
index 1831619..f8731b7 100644
--- a/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
+++ b/web/src/org/jsecurity/web/DefaultWebSecurityManager.java
@@ -22,18 +22,12 @@
import org.apache.commons.logging.LogFactory;
import org.jsecurity.mgt.DefaultSecurityManager;
import org.jsecurity.realm.Realm;
-import org.jsecurity.session.Session;
import org.jsecurity.session.mgt.SessionManager;
-import org.jsecurity.subject.PrincipalCollection;
-import org.jsecurity.subject.Subject;
import org.jsecurity.util.LifecycleUtils;
import org.jsecurity.web.session.DefaultWebSessionManager;
import org.jsecurity.web.session.ServletContainerSessionManager;
import org.jsecurity.web.session.WebSessionManager;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import java.net.InetAddress;
import java.util.Collection;
/**
@@ -66,6 +60,7 @@
public DefaultWebSecurityManager() {
setRememberMeManager(new WebRememberMeManager());
+ setSubjectFactory(new WebSubjectFactory(this, (WebSessionManager) getSessionManager()));
}
public DefaultWebSecurityManager(Realm singleRealm) {
@@ -145,6 +140,7 @@
LifecycleUtils.destroy(getSessionManager());
SessionManager sm = createSessionManager();
setSessionManager(sm);
+ setSubjectFactory(new WebSubjectFactory(this, (WebSessionManager) getSessionManager()));
}
}
@@ -165,99 +161,4 @@
return new DefaultWebSessionManager();
}
}
-
- protected PrincipalCollection getPrincipals(Session session) {
- PrincipalCollection principals = null;
- if (session != null) {
- principals = (PrincipalCollection) session.getAttribute(PRINCIPALS_SESSION_KEY);
- }
- return principals;
- }
-
- protected PrincipalCollection getPrincipals(Session existing, ServletRequest servletRequest, ServletResponse servletResponse) {
- PrincipalCollection principals = getPrincipals(existing);
- if (principals == null) {
- //check remember me:
- principals = getRememberedIdentity();
- if (principals != null && existing != null) {
- existing.setAttribute(PRINCIPALS_SESSION_KEY, principals);
- }
- }
- return principals;
- }
-
- protected boolean isAuthenticated(Session session) {
- Boolean value = null;
- if (session != null) {
- value = (Boolean) session.getAttribute(AUTHENTICATED_SESSION_KEY);
- }
- return value != null && value;
- }
-
- protected boolean isAuthenticated(Session existing, ServletRequest servletRequest, ServletResponse servletResponse) {
- return isAuthenticated(existing);
- }
-
- public Subject createSubject() {
- ServletRequest request = WebUtils.getRequiredServletRequest();
- ServletResponse response = WebUtils.getRequiredServletResponse();
- return createSubject(request, response);
- }
-
- public Subject createSubject(ServletRequest request, ServletResponse response) {
- Session session = ((WebSessionManager) getSessionManager()).getSession(request, response);
- if (session == null) {
- if (log.isTraceEnabled()) {
- log.trace("No session found for the incoming request. The Subject instance created for " +
- "the incoming request will not have an associated Session.");
- }
- }
- return createSubject(session, request, response);
- }
-
- public Subject createSubject(Session existing, ServletRequest request, ServletResponse response) {
- PrincipalCollection principals = getPrincipals(existing, request, response);
- boolean authenticated = isAuthenticated(existing, request, response);
- return createSubject(principals, authenticated, existing, request, response);
- }
-
- protected Subject createSubject(PrincipalCollection principals,
- boolean authenticated,
- Session existing,
- ServletRequest request,
- ServletResponse response) {
- InetAddress inetAddress = WebUtils.getInetAddress(request);
- return createSubject(principals, existing, authenticated, inetAddress);
- }
-
- protected void bind(Subject subject) {
- super.bind(subject);
- ServletRequest request = WebUtils.getRequiredServletRequest();
- ServletResponse response = WebUtils.getRequiredServletResponse();
- bind(subject, request, response);
- }
-
- protected void bind(Subject subject, ServletRequest request, ServletResponse response) {
-
- PrincipalCollection principals = subject.getPrincipals();
- if (principals != null && !principals.isEmpty()) {
- Session session = subject.getSession();
- session.setAttribute(PRINCIPALS_SESSION_KEY, principals);
- } else {
- Session session = subject.getSession(false);
- if (session != null) {
- session.removeAttribute(PRINCIPALS_SESSION_KEY);
- }
- }
-
- if (subject.isAuthenticated()) {
- Session session = subject.getSession();
- session.setAttribute(AUTHENTICATED_SESSION_KEY, subject.isAuthenticated());
- } else {
- Session session = subject.getSession(false);
- if (session != null) {
- session.removeAttribute(AUTHENTICATED_SESSION_KEY);
- }
- }
- }
}
diff --git a/web/src/org/jsecurity/web/WebSubjectFactory.java b/web/src/org/jsecurity/web/WebSubjectFactory.java
new file mode 100644
index 0000000..6952e3d
--- /dev/null
+++ b/web/src/org/jsecurity/web/WebSubjectFactory.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jsecurity.web;
+
+import org.jsecurity.mgt.DefaultSubjectFactory;
+import org.jsecurity.mgt.SecurityManager;
+import org.jsecurity.mgt.SessionSubjectBinder;
+import org.jsecurity.session.Session;
+import org.jsecurity.subject.PrincipalCollection;
+import org.jsecurity.subject.Subject;
+import org.jsecurity.web.session.WebSessionManager;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.net.InetAddress;
+
+/**
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public class WebSubjectFactory extends DefaultSubjectFactory {
+
+ public static final String PRINCIPALS_SESSION_KEY = SessionSubjectBinder.PRINCIPALS_SESSION_KEY;
+ public static final String AUTHENTICATED_SESSION_KEY = SessionSubjectBinder.AUTHENTICATED_SESSION_KEY;
+
+ WebSessionManager webSessionManager;
+
+ public WebSubjectFactory() {
+ }
+
+ public WebSubjectFactory(SecurityManager securityManager) {
+ super(securityManager);
+ }
+
+ public WebSubjectFactory(SecurityManager securityManager, WebSessionManager webSessionManager) {
+ super(securityManager);
+ setWebSessionManager(webSessionManager);
+ }
+
+ public WebSessionManager getWebSessionManager() {
+ return webSessionManager;
+ }
+
+ public void setWebSessionManager(WebSessionManager webSessionManager) {
+ this.webSessionManager = webSessionManager;
+ }
+
+ protected PrincipalCollection getPrincipals(Session existing) {
+ PrincipalCollection principals = null;
+ if (existing != null) {
+ principals = (PrincipalCollection) existing.getAttribute(PRINCIPALS_SESSION_KEY);
+ }
+// if (principals == null) {
+// //check remember me:
+// principals = getRememberedIdentity();
+// if (principals != null && existing != null) {
+// existing.setAttribute(PRINCIPALS_SESSION_KEY, principals);
+// }
+// }
+ return principals;
+ }
+
+ protected boolean isAuthenticated(Session session) {
+ Boolean value = null;
+ if (session != null) {
+ value = (Boolean) session.getAttribute(AUTHENTICATED_SESSION_KEY);
+ }
+ return value != null && value;
+ }
+
+ protected Session getWebSession() {
+ ServletRequest request = WebUtils.getRequiredServletRequest();
+ ServletResponse response = WebUtils.getRequiredServletResponse();
+ return getWebSessionManager().getSession(request, response);
+ }
+
+ @Override
+ public Subject createSubject(PrincipalCollection principals, Session existing, boolean authenticated, InetAddress inetAddress) {
+ Session session = existing;
+ if (session == null) {
+ session = getWebSession();
+ }
+
+ PrincipalCollection pc = principals;
+ if (pc == null) {
+ pc = getPrincipals(session);
+ }
+
+ boolean authc = authenticated;
+ if (!authc) {
+ //check session to be sure:
+ authc = isAuthenticated(session);
+ }
+
+ InetAddress inet = inetAddress;
+ if (inet == null) {
+ inet = WebUtils.getInetAddress(WebUtils.getRequiredServletRequest());
+ }
+
+ return super.createSubject(pc, session, authc, inet);
+ }
+}