View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.subject.support;
20  
21  import org.apache.shiro.SecurityUtils;
22  import org.apache.shiro.UnavailableSecurityManagerException;
23  import org.apache.shiro.authc.AuthenticationInfo;
24  import org.apache.shiro.authc.AuthenticationToken;
25  import org.apache.shiro.authc.HostAuthenticationToken;
26  import org.apache.shiro.mgt.SecurityManager;
27  import org.apache.shiro.session.Session;
28  import org.apache.shiro.subject.PrincipalCollection;
29  import org.apache.shiro.subject.Subject;
30  import org.apache.shiro.subject.SubjectContext;
31  import org.apache.shiro.util.MapContext;
32  import org.apache.shiro.util.StringUtils;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import java.io.Serializable;
37  
38  /**
39   * Default implementation of the {@link SubjectContext} interface.  Note that the getters and setters are not
40   * simple pass-through methods to an underlying attribute;  the getters will employ numerous heuristics to acquire
41   * their data attribute as best as possible (for example, if {@link #getPrincipals} is invoked, if the principals aren't
42   * in the backing map, it might check to see if there is a subject or session in the map and attempt to acquire the
43   * principals from those objects).
44   *
45   * @since 1.0
46   */
47  public class DefaultSubjectContext extends MapContext implements SubjectContext {
48  
49      private static final String SECURITY_MANAGER = DefaultSubjectContext.class.getName() + ".SECURITY_MANAGER";
50  
51      private static final String SESSION_ID = DefaultSubjectContext.class.getName() + ".SESSION_ID";
52  
53      private static final String AUTHENTICATION_TOKEN = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_TOKEN";
54  
55      private static final String AUTHENTICATION_INFO = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_INFO";
56  
57      private static final String SUBJECT = DefaultSubjectContext.class.getName() + ".SUBJECT";
58  
59      private static final String PRINCIPALS = DefaultSubjectContext.class.getName() + ".PRINCIPALS";
60  
61      private static final String SESSION = DefaultSubjectContext.class.getName() + ".SESSION";
62  
63      private static final String AUTHENTICATED = DefaultSubjectContext.class.getName() + ".AUTHENTICATED";
64  
65      private static final String HOST = DefaultSubjectContext.class.getName() + ".HOST";
66  
67      public static final String SESSION_CREATION_ENABLED = DefaultSubjectContext.class.getName() + ".SESSION_CREATION_ENABLED";
68  
69      /**
70       * The session key that is used to store subject principals.
71       */
72      public static final String PRINCIPALS_SESSION_KEY = DefaultSubjectContext.class.getName() + "_PRINCIPALS_SESSION_KEY";
73  
74      /**
75       * The session key that is used to store whether or not the user is authenticated.
76       */
77      public static final String AUTHENTICATED_SESSION_KEY = DefaultSubjectContext.class.getName() + "_AUTHENTICATED_SESSION_KEY";
78  
79      private static final transient Logger log = LoggerFactory.getLogger(DefaultSubjectContext.class);
80  
81      public DefaultSubjectContext() {
82          super();
83      }
84  
85      public DefaultSubjectContext(SubjectContext ctx) {
86          super(ctx);
87      }
88  
89      public SecurityManager getSecurityManager() {
90          return getTypedValue(SECURITY_MANAGER, SecurityManager.class);
91      }
92  
93      public void setSecurityManager(SecurityManager securityManager) {
94          nullSafePut(SECURITY_MANAGER, securityManager);
95      }
96  
97      public SecurityManager resolveSecurityManager() {
98          SecurityManager securityManager = getSecurityManager();
99          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     private static boolean isEmpty(PrincipalCollection pc) {
136         return pc == null || pc.isEmpty();
137     }
138 
139     public void setPrincipals(PrincipalCollection principals) {
140         if (!isEmpty(principals)) {
141             put(PRINCIPALS, principals);
142         }
143     }
144 
145     public PrincipalCollection resolvePrincipals() {
146         PrincipalCollection principals = getPrincipals();
147 
148         if (isEmpty(principals)) {
149             //check to see if they were just authenticated:
150             AuthenticationInfo info = getAuthenticationInfo();
151             if (info != null) {
152                 principals = info.getPrincipals();
153             }
154         }
155 
156         if (isEmpty(principals)) {
157             Subject subject = getSubject();
158             if (subject != null) {
159                 principals = subject.getPrincipals();
160             }
161         }
162 
163         if (isEmpty(principals)) {
164             //try the session:
165             Session session = resolveSession();
166             if (session != null) {
167                 principals = (PrincipalCollection) session.getAttribute(PRINCIPALS_SESSION_KEY);
168             }
169         }
170 
171         return principals;
172     }
173 
174 
175     public Session getSession() {
176         return getTypedValue(SESSION, Session.class);
177     }
178 
179     public void setSession(Session session) {
180         nullSafePut(SESSION, session);
181     }
182 
183     public Session resolveSession() {
184         Session session = getSession();
185         if (session == null) {
186             //try the Subject if it exists:
187             Subject existingSubject = getSubject();
188             if (existingSubject != null) {
189                 session = existingSubject.getSession(false);
190             }
191         }
192         return session;
193     }
194 
195     public boolean isSessionCreationEnabled() {
196         Boolean val = getTypedValue(SESSION_CREATION_ENABLED, Boolean.class);
197         return val == null || val;
198     }
199 
200     public void setSessionCreationEnabled(boolean enabled) {
201         nullSafePut(SESSION_CREATION_ENABLED, enabled);
202     }
203 
204     public boolean isAuthenticated() {
205         Boolean authc = getTypedValue(AUTHENTICATED, Boolean.class);
206         return authc != null && authc;
207     }
208 
209     public void setAuthenticated(boolean authc) {
210         put(AUTHENTICATED, authc);
211     }
212 
213     public boolean resolveAuthenticated() {
214         Boolean authc = getTypedValue(AUTHENTICATED, Boolean.class);
215         if (authc == null) {
216             //see if there is an AuthenticationInfo object.  If so, the very presence of one indicates a successful
217             //authentication attempt:
218             AuthenticationInfo info = getAuthenticationInfo();
219             authc = info != null;
220         }
221         if (!authc) {
222             //fall back to a session check:
223             Session session = resolveSession();
224             if (session != null) {
225                 Boolean sessionAuthc = (Boolean) session.getAttribute(AUTHENTICATED_SESSION_KEY);
226                 authc = sessionAuthc != null && sessionAuthc;
227             }
228         }
229 
230         return authc;
231     }
232 
233     public AuthenticationInfo getAuthenticationInfo() {
234         return getTypedValue(AUTHENTICATION_INFO, AuthenticationInfo.class);
235     }
236 
237     public void setAuthenticationInfo(AuthenticationInfo info) {
238         nullSafePut(AUTHENTICATION_INFO, info);
239     }
240 
241     public AuthenticationToken getAuthenticationToken() {
242         return getTypedValue(AUTHENTICATION_TOKEN, AuthenticationToken.class);
243     }
244 
245     public void setAuthenticationToken(AuthenticationToken token) {
246         nullSafePut(AUTHENTICATION_TOKEN, token);
247     }
248 
249     public String getHost() {
250         return getTypedValue(HOST, String.class);
251     }
252 
253     public void setHost(String host) {
254         if (StringUtils.hasText(host)) {
255             put(HOST, host);
256         }
257     }
258 
259     public String resolveHost() {
260         String host = getHost();
261 
262         if (host == null) {
263             //check to see if there is an AuthenticationToken from which to retrieve it:
264             AuthenticationToken token = getAuthenticationToken();
265             if (token instanceof HostAuthenticationToken) {
266                 host = ((HostAuthenticationToken) token).getHost();
267             }
268         }
269 
270         if (host == null) {
271             Session session = resolveSession();
272             if (session != null) {
273                 host = session.getHost();
274             }
275         }
276 
277         return host;
278     }
279 }