001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.subject.support;
020
021 import org.apache.shiro.SecurityUtils;
022 import org.apache.shiro.UnavailableSecurityManagerException;
023 import org.apache.shiro.authc.AuthenticationInfo;
024 import org.apache.shiro.authc.AuthenticationToken;
025 import org.apache.shiro.authc.HostAuthenticationToken;
026 import org.apache.shiro.mgt.SecurityManager;
027 import org.apache.shiro.session.Session;
028 import org.apache.shiro.subject.PrincipalCollection;
029 import org.apache.shiro.subject.Subject;
030 import org.apache.shiro.subject.SubjectContext;
031 import org.apache.shiro.util.CollectionUtils;
032 import org.apache.shiro.util.MapContext;
033 import org.apache.shiro.util.StringUtils;
034 import org.slf4j.Logger;
035 import org.slf4j.LoggerFactory;
036
037 import java.io.Serializable;
038
039 /**
040 * Default implementation of the {@link SubjectContext} interface. Note that the getters and setters are not
041 * simple pass-through methods to an underlying attribute; the getters will employ numerous heuristics to acquire
042 * their data attribute as best as possible (for example, if {@link #getPrincipals} is invoked, if the principals aren't
043 * in the backing map, it might check to see if there is a subject or session in the map and attempt to acquire the
044 * principals from those objects).
045 *
046 * @author Les Hazlewood
047 * @since 1.0
048 */
049 public class DefaultSubjectContext extends MapContext implements SubjectContext {
050
051 private static final String SECURITY_MANAGER = DefaultSubjectContext.class.getName() + ".SECURITY_MANAGER";
052
053 private static final String SESSION_ID = DefaultSubjectContext.class.getName() + ".SESSION_ID";
054
055 private static final String AUTHENTICATION_TOKEN = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_TOKEN";
056
057 private static final String AUTHENTICATION_INFO = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_INFO";
058
059 private static final String SUBJECT = DefaultSubjectContext.class.getName() + ".SUBJECT";
060
061 private static final String PRINCIPALS = DefaultSubjectContext.class.getName() + ".PRINCIPALS";
062
063 private static final String SESSION = DefaultSubjectContext.class.getName() + ".SESSION";
064
065 private static final String AUTHENTICATED = DefaultSubjectContext.class.getName() + ".AUTHENTICATED";
066
067 private static final String HOST = DefaultSubjectContext.class.getName() + ".HOST";
068
069 /**
070 * The session key that is used to store subject principals.
071 */
072 public static final String PRINCIPALS_SESSION_KEY = DefaultSubjectContext.class.getName() + "_PRINCIPALS_SESSION_KEY";
073
074 /**
075 * The session key that is used to store whether or not the user is authenticated.
076 */
077 public static final String AUTHENTICATED_SESSION_KEY = DefaultSubjectContext.class.getName() + "_AUTHENTICATED_SESSION_KEY";
078
079 private static final transient Logger log = LoggerFactory.getLogger(DefaultSubjectContext.class);
080
081 public DefaultSubjectContext() {
082 super();
083 }
084
085 public DefaultSubjectContext(SubjectContext ctx) {
086 super(ctx);
087 }
088
089 public SecurityManager getSecurityManager() {
090 return getTypedValue(SECURITY_MANAGER, SecurityManager.class);
091 }
092
093 public void setSecurityManager(SecurityManager securityManager) {
094 nullSafePut(SECURITY_MANAGER, securityManager);
095 }
096
097 public SecurityManager resolveSecurityManager() {
098 SecurityManager securityManager = getSecurityManager();
099 if (securityManager == null) {
100 if (log.isDebugEnabled()) {
101 log.debug("No SecurityManager available in subject context map. " +
102 "Falling back to SecurityUtils.getSecurityManager() lookup.");
103 }
104 try {
105 securityManager = SecurityUtils.getSecurityManager();
106 } catch (UnavailableSecurityManagerException e) {
107 if (log.isDebugEnabled()) {
108 log.debug("No SecurityManager available via SecurityUtils. Heuristics exhausted.", e);
109 }
110 }
111 }
112 return securityManager;
113 }
114
115 public Serializable getSessionId() {
116 return getTypedValue(SESSION_ID, Serializable.class);
117 }
118
119 public void setSessionId(Serializable sessionId) {
120 nullSafePut(SESSION_ID, sessionId);
121 }
122
123 public Subject getSubject() {
124 return getTypedValue(SUBJECT, Subject.class);
125 }
126
127 public void setSubject(Subject subject) {
128 nullSafePut(SUBJECT, subject);
129 }
130
131 public PrincipalCollection getPrincipals() {
132 return getTypedValue(PRINCIPALS, PrincipalCollection.class);
133 }
134
135 public void setPrincipals(PrincipalCollection principals) {
136 if (!CollectionUtils.isEmpty(principals)) {
137 put(PRINCIPALS, principals);
138 }
139 }
140
141 public PrincipalCollection resolvePrincipals() {
142 PrincipalCollection principals = getPrincipals();
143
144 if (CollectionUtils.isEmpty(principals)) {
145 //check to see if they were just authenticated:
146 AuthenticationInfo info = getAuthenticationInfo();
147 if (info != null) {
148 principals = info.getPrincipals();
149 }
150 }
151
152 if (CollectionUtils.isEmpty(principals)) {
153 Subject subject = getSubject();
154 if (subject != null) {
155 principals = subject.getPrincipals();
156 }
157 }
158
159 if (CollectionUtils.isEmpty(principals)) {
160 //try the session:
161 Session session = resolveSession();
162 if (session != null) {
163 principals = (PrincipalCollection) session.getAttribute(PRINCIPALS_SESSION_KEY);
164 }
165 }
166
167 return principals;
168 }
169
170
171 public Session getSession() {
172 return getTypedValue(SESSION, Session.class);
173 }
174
175 public void setSession(Session session) {
176 nullSafePut(SESSION, session);
177 }
178
179 public Session resolveSession() {
180 Session session = getSession();
181 if (session == null) {
182 //try the Subject if it exists:
183 Subject existingSubject = getSubject();
184 if (existingSubject != null) {
185 session = existingSubject.getSession(false);
186 }
187 }
188 return session;
189 }
190
191 public boolean isAuthenticated() {
192 Boolean authc = getTypedValue(AUTHENTICATED, Boolean.class);
193 return authc != null && authc;
194 }
195
196 public void setAuthenticated(boolean authc) {
197 put(AUTHENTICATED, authc);
198 }
199
200 public boolean resolveAuthenticated() {
201 Boolean authc = getTypedValue(AUTHENTICATED, Boolean.class);
202 if (authc == null) {
203 //see if there is an AuthenticationInfo object. If so, the very presence of one indicates a successful
204 //authentication attempt:
205 AuthenticationInfo info = getAuthenticationInfo();
206 authc = info != null;
207 }
208 if (!authc) {
209 //fall back to a session check:
210 Session session = resolveSession();
211 if (session != null) {
212 Boolean sessionAuthc = (Boolean) session.getAttribute(AUTHENTICATED_SESSION_KEY);
213 authc = sessionAuthc != null && sessionAuthc;
214 }
215 }
216
217 return authc;
218 }
219
220 public AuthenticationInfo getAuthenticationInfo() {
221 return getTypedValue(AUTHENTICATION_INFO, AuthenticationInfo.class);
222 }
223
224 public void setAuthenticationInfo(AuthenticationInfo info) {
225 nullSafePut(AUTHENTICATION_INFO, info);
226 }
227
228 public AuthenticationToken getAuthenticationToken() {
229 return getTypedValue(AUTHENTICATION_TOKEN, AuthenticationToken.class);
230 }
231
232 public void setAuthenticationToken(AuthenticationToken token) {
233 nullSafePut(AUTHENTICATION_TOKEN, token);
234 }
235
236 public String getHost() {
237 return getTypedValue(HOST, String.class);
238 }
239
240 public void setHost(String host) {
241 if (StringUtils.hasText(host)) {
242 put(HOST, host);
243 }
244 }
245
246 public String resolveHost() {
247 String host = getHost();
248
249 if (host == null) {
250 //check to see if there is an AuthenticationToken from which to retrieve it:
251 AuthenticationToken token = getAuthenticationToken();
252 if (token instanceof HostAuthenticationToken) {
253 host = ((HostAuthenticationToken) token).getHost();
254 }
255 }
256
257 if (host == null) {
258 Session session = resolveSession();
259 if (session != null) {
260 host = session.getHost();
261 }
262 }
263
264 return host;
265 }
266 }