DefaultWebSecurityManager.java
/*
* 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.apache.shiro.web.mgt;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.mgt.SubjectDAO;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionContext;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
import org.apache.shiro.util.LifecycleUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.*;
import org.apache.shiro.web.subject.WebSubject;
import org.apache.shiro.web.subject.WebSubjectContext;
import org.apache.shiro.web.subject.support.DefaultWebSubjectContext;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
import java.util.Collection;
/**
* Default {@link WebSecurityManager WebSecurityManager} implementation used in web-based applications or any
* application that requires HTTP connectivity (SOAP, http remoting, etc).
*
* @since 0.2
*/
public class DefaultWebSecurityManager extends DefaultSecurityManager implements WebSecurityManager {
//TODO - complete JavaDoc
private static final Logger log = LoggerFactory.getLogger(DefaultWebSecurityManager.class);
@Deprecated
public static final String HTTP_SESSION_MODE = "http";
@Deprecated
public static final String NATIVE_SESSION_MODE = "native";
/**
* @deprecated as of 1.2. This should NOT be used for anything other than determining if the sessionMode has changed.
*/
@Deprecated
private String sessionMode;
public DefaultWebSecurityManager() {
super();
((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator());
this.sessionMode = HTTP_SESSION_MODE;
setSubjectFactory(new DefaultWebSubjectFactory());
setRememberMeManager(new CookieRememberMeManager());
setSessionManager(new ServletContainerSessionManager());
}
@SuppressWarnings({"UnusedDeclaration"})
public DefaultWebSecurityManager(Realm singleRealm) {
this();
setRealm(singleRealm);
}
@SuppressWarnings({"UnusedDeclaration"})
public DefaultWebSecurityManager(Collection<Realm> realms) {
this();
setRealms(realms);
}
@Override
protected SubjectContext createSubjectContext() {
return new DefaultWebSubjectContext();
}
@Override
//since 1.2.1 for fixing SHIRO-350
public void setSubjectDAO(SubjectDAO subjectDAO) {
super.setSubjectDAO(subjectDAO);
applySessionManagerToSessionStorageEvaluatorIfPossible();
}
//since 1.2.1 for fixing SHIRO-350
@Override
protected void afterSessionManagerSet() {
super.afterSessionManagerSet();
applySessionManagerToSessionStorageEvaluatorIfPossible();
}
//since 1.2.1 for fixing SHIRO-350:
private void applySessionManagerToSessionStorageEvaluatorIfPossible() {
SubjectDAO subjectDAO = getSubjectDAO();
if (subjectDAO instanceof DefaultSubjectDAO) {
SessionStorageEvaluator evaluator = ((DefaultSubjectDAO)subjectDAO).getSessionStorageEvaluator();
if (evaluator instanceof DefaultWebSessionStorageEvaluator) {
((DefaultWebSessionStorageEvaluator)evaluator).setSessionManager(getSessionManager());
}
}
}
@Override
protected SubjectContext copy(SubjectContext subjectContext) {
if (subjectContext instanceof WebSubjectContext) {
return new DefaultWebSubjectContext((WebSubjectContext) subjectContext);
}
return super.copy(subjectContext);
}
@SuppressWarnings({"UnusedDeclaration"})
@Deprecated
public String getSessionMode() {
return sessionMode;
}
/**
* @param sessionMode
* @deprecated since 1.2
*/
@Deprecated
public void setSessionMode(String sessionMode) {
log.warn("The 'sessionMode' property has been deprecated. Please configure an appropriate WebSessionManager " +
"instance instead of using this property. This property/method will be removed in a later version.");
String mode = sessionMode;
if (mode == null) {
throw new IllegalArgumentException("sessionMode argument cannot be null.");
}
mode = sessionMode.toLowerCase();
if (!HTTP_SESSION_MODE.equals(mode) && !NATIVE_SESSION_MODE.equals(mode)) {
String msg = "Invalid sessionMode [" + sessionMode + "]. Allowed values are " +
"public static final String constants in the " + getClass().getName() + " class: '"
+ HTTP_SESSION_MODE + "' or '" + NATIVE_SESSION_MODE + "', with '" +
HTTP_SESSION_MODE + "' being the default.";
throw new IllegalArgumentException(msg);
}
boolean recreate = this.sessionMode == null || !this.sessionMode.equals(mode);
this.sessionMode = mode;
if (recreate) {
LifecycleUtils.destroy(getSessionManager());
SessionManager sessionManager = createSessionManager(mode);
this.setInternalSessionManager(sessionManager);
}
}
@Override
public void setSessionManager(SessionManager sessionManager) {
this.sessionMode = null;
if (sessionManager != null && !(sessionManager instanceof WebSessionManager)) {
if (log.isWarnEnabled()) {
String msg = "The " + getClass().getName() + " implementation expects SessionManager instances " +
"that implement the " + WebSessionManager.class.getName() + " interface. The " +
"configured instance is of type [" + sessionManager.getClass().getName() + "] which does not " +
"implement this interface.. This may cause unexpected behavior.";
log.warn(msg);
}
}
setInternalSessionManager(sessionManager);
}
/**
* @param sessionManager
* @since 1.2
*/
private void setInternalSessionManager(SessionManager sessionManager) {
super.setSessionManager(sessionManager);
}
/**
* @since 1.0
*/
public boolean isHttpSessionMode() {
SessionManager sessionManager = getSessionManager();
return sessionManager instanceof WebSessionManager && ((WebSessionManager)sessionManager).isServletContainerSessions();
}
protected SessionManager createSessionManager(String sessionMode) {
if (sessionMode == null || !sessionMode.equalsIgnoreCase(NATIVE_SESSION_MODE)) {
log.info("{} mode - enabling ServletContainerSessionManager (HTTP-only Sessions)", HTTP_SESSION_MODE);
return new ServletContainerSessionManager();
} else {
log.info("{} mode - enabling DefaultWebSessionManager (non-HTTP and HTTP Sessions)", NATIVE_SESSION_MODE);
return new DefaultWebSessionManager();
}
}
@Override
protected SessionContext createSessionContext(SubjectContext subjectContext) {
SessionContext sessionContext = super.createSessionContext(subjectContext);
if (subjectContext instanceof WebSubjectContext) {
WebSubjectContext wsc = (WebSubjectContext) subjectContext;
ServletRequest request = wsc.resolveServletRequest();
ServletResponse response = wsc.resolveServletResponse();
DefaultWebSessionContext webSessionContext = new DefaultWebSessionContext(sessionContext);
if (request != null) {
webSessionContext.setServletRequest(request);
}
if (response != null) {
webSessionContext.setServletResponse(response);
}
sessionContext = webSessionContext;
}
return sessionContext;
}
@Override
protected SessionKey getSessionKey(SubjectContext context) {
if (WebUtils.isWeb(context)) {
Serializable sessionId = context.getSessionId();
ServletRequest request = WebUtils.getRequest(context);
ServletResponse response = WebUtils.getResponse(context);
return new WebSessionKey(sessionId, request, response);
} else {
return super.getSessionKey(context);
}
}
@Override
protected void beforeLogout(Subject subject) {
super.beforeLogout(subject);
removeRequestIdentity(subject);
}
protected void removeRequestIdentity(Subject subject) {
if (subject instanceof WebSubject) {
WebSubject webSubject = (WebSubject) subject;
ServletRequest request = webSubject.getServletRequest();
if (request != null) {
request.setAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY, Boolean.TRUE);
}
}
}
}