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.servlet;
020
021 import org.apache.shiro.SecurityUtils;
022 import org.apache.shiro.session.Session;
023 import org.apache.shiro.subject.Subject;
024
025 import javax.servlet.ServletContext;
026 import javax.servlet.http.HttpServletRequest;
027 import javax.servlet.http.HttpServletRequestWrapper;
028 import javax.servlet.http.HttpSession;
029 import java.security.Principal;
030
031
032 /**
033 * A {@code ShiroHttpServletRequest} wraps the Servlet container's original {@code ServletRequest} instance, but ensures
034 * that all {@link HttpServletRequest} invocations that require Shiro's support ({@link #getRemoteUser getRemoteUser},
035 * {@link #getSession getSession}, etc) can be executed first by Shiro as necessary before allowing the underlying
036 * Servlet container instance's method to be invoked.
037 *
038 * @since 0.2
039 */
040 public class ShiroHttpServletRequest extends HttpServletRequestWrapper {
041
042 //TODO - complete JavaDoc
043
044 //The following 7 constants support the Shiro's implementation of the Servlet Specification
045 public static final String COOKIE_SESSION_ID_SOURCE = "cookie";
046 public static final String URL_SESSION_ID_SOURCE = "url";
047 public static final String REFERENCED_SESSION_ID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID";
048 public static final String REFERENCED_SESSION_ID_IS_VALID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID_VALID";
049 public static final String REFERENCED_SESSION_IS_NEW = ShiroHttpServletRequest.class.getName() + "_REFERENCED_SESSION_IS_NEW";
050 public static final String REFERENCED_SESSION_ID_SOURCE = ShiroHttpServletRequest.class.getName() + "REFERENCED_SESSION_ID_SOURCE";
051 public static final String IDENTITY_REMOVED_KEY = ShiroHttpServletRequest.class.getName() + "_IDENTITY_REMOVED_KEY";
052
053 protected ServletContext servletContext = null;
054
055 protected HttpSession session = null;
056 protected boolean httpSessions = true;
057
058 public ShiroHttpServletRequest(HttpServletRequest wrapped, ServletContext servletContext, boolean httpSessions) {
059 super(wrapped);
060 this.servletContext = servletContext;
061 this.httpSessions = httpSessions;
062 }
063
064 public boolean isHttpSessions() {
065 return httpSessions;
066 }
067
068 public String getRemoteUser() {
069 String remoteUser;
070 Object scPrincipal = getSubjectPrincipal();
071 if (scPrincipal != null) {
072 if (scPrincipal instanceof String) {
073 return (String) scPrincipal;
074 } else if (scPrincipal instanceof Principal) {
075 remoteUser = ((Principal) scPrincipal).getName();
076 } else {
077 remoteUser = scPrincipal.toString();
078 }
079 } else {
080 remoteUser = super.getRemoteUser();
081 }
082 return remoteUser;
083 }
084
085 protected Subject getSubject() {
086 return SecurityUtils.getSubject();
087 }
088
089 protected Object getSubjectPrincipal() {
090 Object userPrincipal = null;
091 Subject subject = getSubject();
092 if (subject != null) {
093 userPrincipal = subject.getPrincipal();
094 }
095 return userPrincipal;
096 }
097
098 public boolean isUserInRole(String s) {
099 Subject subject = getSubject();
100 boolean inRole = (subject != null && subject.hasRole(s));
101 if (!inRole) {
102 inRole = super.isUserInRole(s);
103 }
104 return inRole;
105 }
106
107 public Principal getUserPrincipal() {
108 Principal userPrincipal;
109 Object scPrincipal = getSubjectPrincipal();
110 if (scPrincipal != null) {
111 if (scPrincipal instanceof Principal) {
112 userPrincipal = (Principal) scPrincipal;
113 } else {
114 userPrincipal = new ObjectPrincipal(scPrincipal);
115 }
116 } else {
117 userPrincipal = super.getUserPrincipal();
118 }
119 return userPrincipal;
120 }
121
122 public String getRequestedSessionId() {
123 String requestedSessionId = null;
124 if (isHttpSessions()) {
125 requestedSessionId = super.getRequestedSessionId();
126 } else {
127 Object sessionId = getAttribute(REFERENCED_SESSION_ID);
128 if (sessionId != null) {
129 requestedSessionId = sessionId.toString();
130 }
131 }
132
133 return requestedSessionId;
134 }
135
136 public HttpSession getSession(boolean create) {
137
138 HttpSession httpSession;
139
140 if (isHttpSessions()) {
141 httpSession = super.getSession(create);
142 } else {
143 if (this.session == null) {
144
145 boolean existing = getSubject().getSession(false) != null;
146
147 Session jsecSession = getSubject().getSession(create);
148 if (jsecSession != null) {
149 this.session = new ShiroHttpSession(jsecSession, this, this.servletContext);
150 if (!existing) {
151 setAttribute(REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
152 }
153 }
154 }
155 httpSession = this.session;
156 }
157
158 return httpSession;
159 }
160
161
162 public HttpSession getSession() {
163 return getSession(true);
164 }
165
166 public boolean isRequestedSessionIdValid() {
167 if (isHttpSessions()) {
168 return super.isRequestedSessionIdValid();
169 } else {
170 Boolean value = (Boolean) getAttribute(REFERENCED_SESSION_ID_IS_VALID);
171 return (value != null && value.equals(Boolean.TRUE));
172 }
173 }
174
175 public boolean isRequestedSessionIdFromCookie() {
176 if (isHttpSessions()) {
177 return super.isRequestedSessionIdFromCookie();
178 } else {
179 String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
180 return value != null && value.equals(COOKIE_SESSION_ID_SOURCE);
181 }
182 }
183
184 public boolean isRequestedSessionIdFromURL() {
185 if (isHttpSessions()) {
186 return super.isRequestedSessionIdFromURL();
187 } else {
188 String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
189 return value != null && value.equals(URL_SESSION_ID_SOURCE);
190 }
191 }
192
193 public boolean isRequestedSessionIdFromUrl() {
194 return isRequestedSessionIdFromURL();
195 }
196
197 private class ObjectPrincipal implements java.security.Principal {
198 private Object object = null;
199
200 public ObjectPrincipal(Object object) {
201 this.object = object;
202 }
203
204 public Object getObject() {
205 return object;
206 }
207
208 public String getName() {
209 return getObject().toString();
210 }
211
212 public int hashCode() {
213 return object.hashCode();
214 }
215
216 public boolean equals(Object o) {
217 if (o instanceof ObjectPrincipal) {
218 ObjectPrincipal op = (ObjectPrincipal) o;
219 return getObject().equals(op.getObject());
220 }
221 return false;
222 }
223
224 public String toString() {
225 return object.toString();
226 }
227 }
228 }