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.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 private static final String SECURITY_MANAGER = DefaultSubjectContext.class.getName() + ".SECURITY_MANAGER"; 050 051 private static final String SESSION_ID = DefaultSubjectContext.class.getName() + ".SESSION_ID"; 052 053 private static final String AUTHENTICATION_TOKEN = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_TOKEN"; 054 055 private static final String AUTHENTICATION_INFO = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_INFO"; 056 057 private static final String SUBJECT = DefaultSubjectContext.class.getName() + ".SUBJECT"; 058 059 private static final String PRINCIPALS = DefaultSubjectContext.class.getName() + ".PRINCIPALS"; 060 061 private static final String SESSION = DefaultSubjectContext.class.getName() + ".SESSION"; 062 063 private static final String AUTHENTICATED = DefaultSubjectContext.class.getName() + ".AUTHENTICATED"; 064 065 private static final String HOST = DefaultSubjectContext.class.getName() + ".HOST"; 066 067 public static final String SESSION_CREATION_ENABLED = DefaultSubjectContext.class.getName() + ".SESSION_CREATION_ENABLED"; 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 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}