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.web.mgt;
020
021 import org.apache.shiro.mgt.DefaultSecurityManager;
022 import org.apache.shiro.realm.Realm;
023 import org.apache.shiro.session.mgt.SessionContext;
024 import org.apache.shiro.session.mgt.SessionKey;
025 import org.apache.shiro.session.mgt.SessionManager;
026 import org.apache.shiro.subject.Subject;
027 import org.apache.shiro.subject.SubjectContext;
028 import org.apache.shiro.util.LifecycleUtils;
029 import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
030 import org.apache.shiro.web.session.mgt.DefaultWebSessionContext;
031 import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
032 import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
033 import org.apache.shiro.web.session.mgt.WebSessionKey;
034 import org.apache.shiro.web.subject.WebSubject;
035 import org.apache.shiro.web.subject.WebSubjectContext;
036 import org.apache.shiro.web.subject.support.DefaultWebSubjectContext;
037 import org.apache.shiro.web.util.WebUtils;
038 import org.slf4j.Logger;
039 import org.slf4j.LoggerFactory;
040
041 import javax.servlet.ServletRequest;
042 import javax.servlet.ServletResponse;
043 import java.io.Serializable;
044 import java.util.Collection;
045
046
047 /**
048 * Default {@link WebSecurityManager WebSecurityManager} implementation used in web-based applications or any
049 * application that requires HTTP connectivity (SOAP, http remoting, etc).
050 *
051 * @since 0.2
052 */
053 public class DefaultWebSecurityManager extends DefaultSecurityManager implements WebSecurityManager {
054
055 //TODO - complete JavaDoc
056
057 private static final Logger log = LoggerFactory.getLogger(DefaultWebSecurityManager.class);
058
059 public static final String HTTP_SESSION_MODE = "http";
060 public static final String NATIVE_SESSION_MODE = "native";
061
062 private String sessionMode;
063
064 public DefaultWebSecurityManager() {
065 super();
066 this.sessionMode = HTTP_SESSION_MODE;
067 setSubjectFactory(new DefaultWebSubjectFactory());
068 setRememberMeManager(new CookieRememberMeManager());
069 setSessionManager(new ServletContainerSessionManager());
070 }
071
072 @SuppressWarnings({"UnusedDeclaration"})
073 public DefaultWebSecurityManager(Realm singleRealm) {
074 this();
075 setRealm(singleRealm);
076 }
077
078 @SuppressWarnings({"UnusedDeclaration"})
079 public DefaultWebSecurityManager(Collection<Realm> realms) {
080 this();
081 setRealms(realms);
082 }
083
084 @Override
085 protected SubjectContext createSubjectContext() {
086 return new DefaultWebSubjectContext();
087 }
088
089 @Override
090 protected SubjectContext copy(SubjectContext subjectContext) {
091 if (subjectContext instanceof WebSubjectContext) {
092 return new DefaultWebSubjectContext((WebSubjectContext) subjectContext);
093 }
094 return super.copy(subjectContext);
095 }
096
097 @SuppressWarnings({"UnusedDeclaration"})
098 public String getSessionMode() {
099 return sessionMode;
100 }
101
102 public void setSessionMode(String sessionMode) {
103 String mode = sessionMode;
104 if (mode == null) {
105 throw new IllegalArgumentException("sessionMode argument cannot be null.");
106 }
107 mode = sessionMode.toLowerCase();
108 if (!HTTP_SESSION_MODE.equals(mode) && !NATIVE_SESSION_MODE.equals(mode)) {
109 String msg = "Invalid sessionMode [" + sessionMode + "]. Allowed values are " +
110 "public static final String constants in the " + getClass().getName() + " class: '"
111 + HTTP_SESSION_MODE + "' or '" + NATIVE_SESSION_MODE + "', with '" +
112 HTTP_SESSION_MODE + "' being the default.";
113 throw new IllegalArgumentException(msg);
114 }
115 boolean recreate = this.sessionMode == null || !this.sessionMode.equals(mode);
116 this.sessionMode = mode;
117 if (recreate) {
118 LifecycleUtils.destroy(getSessionManager());
119 SessionManager sessionManager = createSessionManager(mode);
120 setSessionManager(sessionManager);
121 }
122 }
123
124 /**
125 * @since 1.0
126 */
127 public boolean isHttpSessionMode() {
128 return this.sessionMode == null || this.sessionMode.equals(HTTP_SESSION_MODE);
129 }
130
131 protected SessionManager createSessionManager(String sessionMode) {
132 if (sessionMode == null || sessionMode.equalsIgnoreCase(HTTP_SESSION_MODE)) {
133 if (log.isInfoEnabled()) {
134 log.info(HTTP_SESSION_MODE + " mode - enabling ServletContainerSessionManager (HTTP-only Sessions)");
135 }
136 return new ServletContainerSessionManager();
137 } else {
138 if (log.isInfoEnabled()) {
139 log.info(NATIVE_SESSION_MODE + " mode - enabling DefaultWebSessionManager (HTTP + heterogeneous-client sessions)");
140 }
141 return new DefaultWebSessionManager();
142 }
143 }
144
145 @Override
146 protected SessionContext createSessionContext(SubjectContext subjectContext) {
147 SessionContext sessionContext = super.createSessionContext(subjectContext);
148 if (subjectContext instanceof WebSubjectContext) {
149 WebSubjectContext wsc = (WebSubjectContext) subjectContext;
150 ServletRequest request = wsc.resolveServletRequest();
151 ServletResponse response = wsc.resolveServletResponse();
152 DefaultWebSessionContext webSessionContext = new DefaultWebSessionContext(sessionContext);
153 if (request != null) {
154 webSessionContext.setServletRequest(request);
155 }
156 if (response != null) {
157 webSessionContext.setServletResponse(response);
158 }
159
160 sessionContext = webSessionContext;
161 }
162 return sessionContext;
163 }
164
165 @Override
166 protected SessionKey getSessionKey(SubjectContext context) {
167 if (WebUtils.isWeb(context)) {
168 Serializable sessionId = context.getSessionId();
169 ServletRequest request = WebUtils.getRequest(context);
170 ServletResponse response = WebUtils.getResponse(context);
171 return new WebSessionKey(sessionId, request, response);
172 } else {
173 return super.getSessionKey(context);
174
175 }
176 }
177
178 @Override
179 protected void beforeLogout(Subject subject) {
180 super.beforeLogout(subject);
181 removeRequestIdentity(subject);
182 }
183
184 protected void removeRequestIdentity(Subject subject) {
185 if (subject instanceof WebSubject) {
186 WebSubject webSubject = (WebSubject) subject;
187 ServletRequest request = webSubject.getServletRequest();
188 if (request != null) {
189 request.setAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY, Boolean.TRUE);
190 }
191 }
192 }
193 }