View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.web.servlet;
20  
21  import org.apache.shiro.SecurityUtils;
22  import org.apache.shiro.session.Session;
23  import org.apache.shiro.subject.Subject;
24  import org.apache.shiro.subject.support.DisabledSessionException;
25  import org.apache.shiro.web.util.WebUtils;
26  
27  import javax.servlet.ServletContext;
28  import javax.servlet.http.HttpServletRequest;
29  import javax.servlet.http.HttpServletRequestWrapper;
30  import javax.servlet.http.HttpSession;
31  import java.security.Principal;
32  
33  
34  /**
35   * A {@code ShiroHttpServletRequest} wraps the Servlet container's original {@code ServletRequest} instance, but ensures
36   * that all {@link HttpServletRequest} invocations that require Shiro's support ({@link #getRemoteUser getRemoteUser},
37   * {@link #getSession getSession}, etc) can be executed first by Shiro as necessary before allowing the underlying
38   * Servlet container instance's method to be invoked.
39   *
40   * @since 0.2
41   */
42  public class ShiroHttpServletRequest extends HttpServletRequestWrapper {
43  
44      //TODO - complete JavaDoc
45  
46      //The following 7 constants support the Shiro's implementation of the Servlet Specification
47      public static final String COOKIE_SESSION_ID_SOURCE = "cookie";
48      public static final String URL_SESSION_ID_SOURCE = "url";
49      public static final String REFERENCED_SESSION_ID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID";
50      public static final String REFERENCED_SESSION_ID_IS_VALID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID_VALID";
51      public static final String REFERENCED_SESSION_IS_NEW = ShiroHttpServletRequest.class.getName() + "_REFERENCED_SESSION_IS_NEW";
52      public static final String REFERENCED_SESSION_ID_SOURCE = ShiroHttpServletRequest.class.getName() + "REFERENCED_SESSION_ID_SOURCE";
53      public static final String IDENTITY_REMOVED_KEY = ShiroHttpServletRequest.class.getName() + "_IDENTITY_REMOVED_KEY";
54      public static final String SESSION_ID_URL_REWRITING_ENABLED = ShiroHttpServletRequest.class.getName() + "_SESSION_ID_URL_REWRITING_ENABLED";
55  
56      protected ServletContext servletContext = null;
57  
58      protected HttpSession session = null;
59      protected boolean httpSessions = true;
60  
61      public ShiroHttpServletRequest(HttpServletRequest wrapped, ServletContext servletContext, boolean httpSessions) {
62          super(wrapped);
63          this.servletContext = servletContext;
64          this.httpSessions = httpSessions;
65      }
66  
67      public boolean isHttpSessions() {
68          return httpSessions;
69      }
70  
71      public String getRemoteUser() {
72          String remoteUser;
73          Object scPrincipal = getSubjectPrincipal();
74          if (scPrincipal != null) {
75              if (scPrincipal instanceof String) {
76                  return (String) scPrincipal;
77              } else if (scPrincipal instanceof Principal) {
78                  remoteUser = ((Principal) scPrincipal).getName();
79              } else {
80                  remoteUser = scPrincipal.toString();
81              }
82          } else {
83              remoteUser = super.getRemoteUser();
84          }
85          return remoteUser;
86      }
87  
88      protected Subject getSubject() {
89          return SecurityUtils.getSubject();
90      }
91  
92      protected Object getSubjectPrincipal() {
93          Object userPrincipal = null;
94          Subject subject = getSubject();
95          if (subject != null) {
96              userPrincipal = subject.getPrincipal();
97          }
98          return userPrincipal;
99      }
100 
101     public boolean isUserInRole(String s) {
102         Subject subject = getSubject();
103         boolean inRole = (subject != null && subject.hasRole(s));
104         if (!inRole) {
105             inRole = super.isUserInRole(s);
106         }
107         return inRole;
108     }
109 
110     public Principal getUserPrincipal() {
111         Principal userPrincipal;
112         Object scPrincipal = getSubjectPrincipal();
113         if (scPrincipal != null) {
114             if (scPrincipal instanceof Principal) {
115                 userPrincipal = (Principal) scPrincipal;
116             } else {
117                 userPrincipal = new ObjectPrincipal(scPrincipal);
118             }
119         } else {
120             userPrincipal = super.getUserPrincipal();
121         }
122         return userPrincipal;
123     }
124 
125     public String getRequestedSessionId() {
126         String requestedSessionId = null;
127         if (isHttpSessions()) {
128             requestedSessionId = super.getRequestedSessionId();
129         } else {
130             Object sessionId = getAttribute(REFERENCED_SESSION_ID);
131             if (sessionId != null) {
132                 requestedSessionId = sessionId.toString();
133             }
134         }
135 
136         return requestedSessionId;
137     }
138 
139     public HttpSession getSession(boolean create) {
140 
141         HttpSession httpSession;
142 
143         if (isHttpSessions()) {
144             httpSession = super.getSession(false);
145             if (httpSession == null && create) {
146                 //Shiro 1.2: assert that creation is enabled (SHIRO-266):
147                 if (WebUtils._isSessionCreationEnabled(this)) {
148                     httpSession = super.getSession(create);
149                 } else {
150                     throw newNoSessionCreationException();
151                 }
152             }
153         } else {
154             boolean existing = getSubject().getSession(false) != null;
155             
156             if (this.session == null || !existing) {
157                 Session shiroSession = getSubject().getSession(create);
158                 if (shiroSession != null) {
159                     this.session = new ShiroHttpSession(shiroSession, this, this.servletContext);
160                     if (!existing) {
161                         setAttribute(REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
162                     }
163                 } else if (this.session != null) {
164                     this.session = null;
165                 }
166             }
167             httpSession = this.session;
168         }
169 
170         return httpSession;
171     }
172 
173     /**
174      * Constructs and returns a {@link DisabledSessionException} with an appropriate message explaining why
175      * session creation has been disabled.
176      *
177      * @return a new DisabledSessionException with appropriate no creation message
178      * @since 1.2
179      */
180     private DisabledSessionException newNoSessionCreationException() {
181         String msg = "Session creation has been disabled for the current request.  This exception indicates " +
182                 "that there is either a programming error (using a session when it should never be " +
183                 "used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created " +
184                 "for the current request.  See the " + DisabledSessionException.class.getName() + " JavaDoc " +
185                 "for more.";
186         return new DisabledSessionException(msg);
187     }
188 
189     public HttpSession getSession() {
190         return getSession(true);
191     }
192 
193     public boolean isRequestedSessionIdValid() {
194         if (isHttpSessions()) {
195             return super.isRequestedSessionIdValid();
196         } else {
197             Boolean value = (Boolean) getAttribute(REFERENCED_SESSION_ID_IS_VALID);
198             return (value != null && value.equals(Boolean.TRUE));
199         }
200     }
201 
202     public boolean isRequestedSessionIdFromCookie() {
203         if (isHttpSessions()) {
204             return super.isRequestedSessionIdFromCookie();
205         } else {
206             String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
207             return value != null && value.equals(COOKIE_SESSION_ID_SOURCE);
208         }
209     }
210 
211     public boolean isRequestedSessionIdFromURL() {
212         if (isHttpSessions()) {
213             return super.isRequestedSessionIdFromURL();
214         } else {
215             String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
216             return value != null && value.equals(URL_SESSION_ID_SOURCE);
217         }
218     }
219 
220     public boolean isRequestedSessionIdFromUrl() {
221         return isRequestedSessionIdFromURL();
222     }
223 
224     private class ObjectPrincipal implements java.security.Principal {
225         private Object object = null;
226 
227         public ObjectPrincipal(Object object) {
228             this.object = object;
229         }
230 
231         public Object getObject() {
232             return object;
233         }
234 
235         public String getName() {
236             return getObject().toString();
237         }
238 
239         public int hashCode() {
240             return object.hashCode();
241         }
242 
243         public boolean equals(Object o) {
244             if (o instanceof ObjectPrincipal) {
245                 ObjectPrincipal op = (ObjectPrincipal) o;
246                 return getObject().equals(op.getObject());
247             }
248             return false;
249         }
250 
251         public String toString() {
252             return object.toString();
253         }
254     }
255 }