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 */ 019package org.apache.shiro.subject.support; 020 021import org.apache.shiro.SecurityUtils; 022import org.apache.shiro.UnavailableSecurityManagerException; 023import org.apache.shiro.authc.AuthenticationInfo; 024import org.apache.shiro.authc.AuthenticationToken; 025import org.apache.shiro.authc.HostAuthenticationToken; 026import org.apache.shiro.mgt.SecurityManager; 027import org.apache.shiro.session.Session; 028import org.apache.shiro.subject.PrincipalCollection; 029import org.apache.shiro.subject.Subject; 030import org.apache.shiro.subject.SubjectContext; 031import org.apache.shiro.util.MapContext; 032import org.apache.shiro.lang.util.StringUtils; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import java.io.Serializable; 037 038/** 039 * Default implementation of the {@link SubjectContext} interface. Note that the getters and setters are not 040 * simple pass-through methods to an underlying attribute; the getters will employ numerous heuristics to acquire 041 * their data attribute as best as possible (for example, if {@link #getPrincipals} is invoked, if the principals aren't 042 * in the backing map, it might check to see if there is a subject or session in the map and attempt to acquire the 043 * principals from those objects). 044 * 045 * @since 1.0 046 */ 047public class DefaultSubjectContext extends MapContext implements SubjectContext { 048 049 /** 050 * session creation enabled key. 051 */ 052 public static final String SESSION_CREATION_ENABLED = DefaultSubjectContext.class.getName() + ".SESSION_CREATION_ENABLED"; 053 054 /** 055 * The session key that is used to store subject principals. 056 */ 057 public static final String PRINCIPALS_SESSION_KEY = DefaultSubjectContext.class.getName() + "_PRINCIPALS_SESSION_KEY"; 058 059 /** 060 * The session key that is used to store whether or not the user is authenticated. 061 */ 062 public static final String AUTHENTICATED_SESSION_KEY = DefaultSubjectContext.class.getName() + "_AUTHENTICATED_SESSION_KEY"; 063 064 private static final String SECURITY_MANAGER = DefaultSubjectContext.class.getName() + ".SECURITY_MANAGER"; 065 066 private static final String SESSION_ID = DefaultSubjectContext.class.getName() + ".SESSION_ID"; 067 068 private static final String AUTHENTICATION_TOKEN = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_TOKEN"; 069 070 private static final String AUTHENTICATION_INFO = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_INFO"; 071 072 private static final String SUBJECT = DefaultSubjectContext.class.getName() + ".SUBJECT"; 073 074 private static final String PRINCIPALS = DefaultSubjectContext.class.getName() + ".PRINCIPALS"; 075 076 private static final String SESSION = DefaultSubjectContext.class.getName() + ".SESSION"; 077 078 private static final String AUTHENTICATED = DefaultSubjectContext.class.getName() + ".AUTHENTICATED"; 079 080 private static final String HOST = DefaultSubjectContext.class.getName() + ".HOST"; 081 082 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSubjectContext.class); 083 084 public DefaultSubjectContext() { 085 super(); 086 } 087 088 public DefaultSubjectContext(SubjectContext ctx) { 089 super(ctx); 090 } 091 092 public SecurityManager getSecurityManager() { 093 return getTypedValue(SECURITY_MANAGER, SecurityManager.class); 094 } 095 096 public void setSecurityManager(SecurityManager securityManager) { 097 nullSafePut(SECURITY_MANAGER, securityManager); 098 } 099 100 public SecurityManager resolveSecurityManager() { 101 SecurityManager securityManager = getSecurityManager(); 102 if (securityManager == null) { 103 if (LOGGER.isDebugEnabled()) { 104 LOGGER.debug("No SecurityManager available in subject context map. " 105 + "Falling back to SecurityUtils.getSecurityManager() lookup."); 106 } 107 try { 108 securityManager = SecurityUtils.getSecurityManager(); 109 } catch (UnavailableSecurityManagerException e) { 110 if (LOGGER.isDebugEnabled()) { 111 LOGGER.debug("No SecurityManager available via SecurityUtils. Heuristics exhausted.", e); 112 } 113 } 114 } 115 return securityManager; 116 } 117 118 public Serializable getSessionId() { 119 return getTypedValue(SESSION_ID, Serializable.class); 120 } 121 122 public void setSessionId(Serializable sessionId) { 123 nullSafePut(SESSION_ID, sessionId); 124 } 125 126 public Subject getSubject() { 127 return getTypedValue(SUBJECT, Subject.class); 128 } 129 130 public void setSubject(Subject subject) { 131 nullSafePut(SUBJECT, subject); 132 } 133 134 public PrincipalCollection getPrincipals() { 135 return getTypedValue(PRINCIPALS, PrincipalCollection.class); 136 } 137 138 private static boolean isEmpty(PrincipalCollection pc) { 139 return pc == null || pc.isEmpty(); 140 } 141 142 public void setPrincipals(PrincipalCollection principals) { 143 if (!isEmpty(principals)) { 144 put(PRINCIPALS, principals); 145 } 146 } 147 148 public PrincipalCollection resolvePrincipals() { 149 PrincipalCollection principals = getPrincipals(); 150 151 if (isEmpty(principals)) { 152 //check to see if they were just authenticated: 153 AuthenticationInfo info = getAuthenticationInfo(); 154 if (info != null) { 155 principals = info.getPrincipals(); 156 } 157 } 158 159 if (isEmpty(principals)) { 160 Subject subject = getSubject(); 161 if (subject != null) { 162 principals = subject.getPrincipals(); 163 } 164 } 165 166 if (isEmpty(principals)) { 167 //try the session: 168 Session session = resolveSession(); 169 if (session != null) { 170 principals = (PrincipalCollection) session.getAttribute(PRINCIPALS_SESSION_KEY); 171 } 172 } 173 174 return principals; 175 } 176 177 178 public Session getSession() { 179 return getTypedValue(SESSION, Session.class); 180 } 181 182 public void setSession(Session session) { 183 nullSafePut(SESSION, session); 184 } 185 186 public Session resolveSession() { 187 Session session = getSession(); 188 if (session == null) { 189 //try the Subject if it exists: 190 Subject existingSubject = getSubject(); 191 if (existingSubject != null) { 192 session = existingSubject.getSession(false); 193 } 194 } 195 return session; 196 } 197 198 public boolean isSessionCreationEnabled() { 199 Boolean val = getTypedValue(SESSION_CREATION_ENABLED, Boolean.class); 200 return val == null || val; 201 } 202 203 public void setSessionCreationEnabled(boolean enabled) { 204 nullSafePut(SESSION_CREATION_ENABLED, enabled); 205 } 206 207 public boolean isAuthenticated() { 208 Boolean authc = getTypedValue(AUTHENTICATED, Boolean.class); 209 return authc != null && authc; 210 } 211 212 public void setAuthenticated(boolean authc) { 213 put(AUTHENTICATED, authc); 214 } 215 216 public boolean resolveAuthenticated() { 217 Boolean authc = getTypedValue(AUTHENTICATED, Boolean.class); 218 if (authc == null) { 219 //see if there is an AuthenticationInfo object. If so, the very presence of one indicates a successful 220 //authentication attempt: 221 AuthenticationInfo info = getAuthenticationInfo(); 222 authc = info != null; 223 } 224 if (!authc) { 225 //fall back to a session check: 226 Session session = resolveSession(); 227 if (session != null) { 228 Boolean sessionAuthc = (Boolean) session.getAttribute(AUTHENTICATED_SESSION_KEY); 229 authc = sessionAuthc != null && sessionAuthc; 230 } 231 } 232 233 return authc; 234 } 235 236 public AuthenticationInfo getAuthenticationInfo() { 237 return getTypedValue(AUTHENTICATION_INFO, AuthenticationInfo.class); 238 } 239 240 public void setAuthenticationInfo(AuthenticationInfo info) { 241 nullSafePut(AUTHENTICATION_INFO, info); 242 } 243 244 public AuthenticationToken getAuthenticationToken() { 245 return getTypedValue(AUTHENTICATION_TOKEN, AuthenticationToken.class); 246 } 247 248 public void setAuthenticationToken(AuthenticationToken token) { 249 nullSafePut(AUTHENTICATION_TOKEN, token); 250 } 251 252 public String getHost() { 253 return getTypedValue(HOST, String.class); 254 } 255 256 public void setHost(String host) { 257 if (StringUtils.hasText(host)) { 258 put(HOST, host); 259 } 260 } 261 262 public String resolveHost() { 263 String host = getHost(); 264 265 if (host == null) { 266 //check to see if there is an AuthenticationToken from which to retrieve it: 267 AuthenticationToken token = getAuthenticationToken(); 268 if (token instanceof HostAuthenticationToken) { 269 host = ((HostAuthenticationToken) token).getHost(); 270 } 271 } 272 273 if (host == null) { 274 Session session = resolveSession(); 275 if (session != null) { 276 host = session.getHost(); 277 } 278 } 279 280 return host; 281 } 282}