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  @SuppressWarnings({"checkstyle:JavadocVariable"})
43  public class ShiroHttpServletRequest extends HttpServletRequestWrapper {
44  
45      //The following 7 constants support the Shiro's implementation of the Servlet Specification
46      public static final String COOKIE_SESSION_ID_SOURCE = "cookie";
47      public static final String URL_SESSION_ID_SOURCE = "url";
48      public static final String REFERENCED_SESSION_ID = ShiroHttpServletRequest.class.getName()
49              + "_REQUESTED_SESSION_ID";
50      public static final String REFERENCED_SESSION_ID_IS_VALID = ShiroHttpServletRequest.class.getName()
51              + "_REQUESTED_SESSION_ID_VALID";
52      public static final String REFERENCED_SESSION_IS_NEW = ShiroHttpServletRequest.class.getName()
53              + "_REFERENCED_SESSION_IS_NEW";
54      public static final String REFERENCED_SESSION_ID_SOURCE = ShiroHttpServletRequest.class.getName()
55              + "REFERENCED_SESSION_ID_SOURCE";
56      public static final String IDENTITY_REMOVED_KEY = ShiroHttpServletRequest.class.getName()
57              + "_IDENTITY_REMOVED_KEY";
58      public static final String SESSION_ID_URL_REWRITING_ENABLED = ShiroHttpServletRequest.class.getName()
59              + "_SESSION_ID_URL_REWRITING_ENABLED";
60  
61      protected ServletContext servletContext;
62  
63      protected HttpSession session;
64      protected boolean httpSessions;
65  
66      public ShiroHttpServletRequest(HttpServletRequest wrapped, ServletContext servletContext, boolean httpSessions) {
67          super(wrapped);
68          this.servletContext = servletContext;
69          this.httpSessions = httpSessions;
70      }
71  
72      public boolean isHttpSessions() {
73          return httpSessions;
74      }
75  
76      public String getRemoteUser() {
77          String remoteUser;
78          Object scPrincipal = getSubjectPrincipal();
79          if (scPrincipal != null) {
80              if (scPrincipal instanceof String) {
81                  return (String) scPrincipal;
82              } else if (scPrincipal instanceof Principal) {
83                  remoteUser = ((Principal) scPrincipal).getName();
84              } else {
85                  remoteUser = scPrincipal.toString();
86              }
87          } else {
88              remoteUser = super.getRemoteUser();
89          }
90          return remoteUser;
91      }
92  
93      protected Subject getSubject() {
94          return SecurityUtils.getSubject();
95      }
96  
97      protected Object getSubjectPrincipal() {
98          Object userPrincipal = null;
99          Subject subject = getSubject();
100         if (subject != null) {
101             userPrincipal = subject.getPrincipal();
102         }
103         return userPrincipal;
104     }
105 
106     public boolean isUserInRole(String s) {
107         Subject subject = getSubject();
108         boolean inRole = (subject != null && subject.hasRole(s));
109         if (!inRole) {
110             inRole = super.isUserInRole(s);
111         }
112         return inRole;
113     }
114 
115     public Principal getUserPrincipal() {
116         Principal userPrincipal;
117         Object scPrincipal = getSubjectPrincipal();
118         if (scPrincipal != null) {
119             if (scPrincipal instanceof Principal) {
120                 userPrincipal = (Principal) scPrincipal;
121             } else {
122                 userPrincipal = new ObjectPrincipal(scPrincipal);
123             }
124         } else {
125             userPrincipal = super.getUserPrincipal();
126         }
127         return userPrincipal;
128     }
129 
130     public String getRequestedSessionId() {
131         String requestedSessionId = null;
132         if (isHttpSessions()) {
133             requestedSessionId = super.getRequestedSessionId();
134         } else {
135             Object sessionId = getAttribute(REFERENCED_SESSION_ID);
136             if (sessionId != null) {
137                 requestedSessionId = sessionId.toString();
138             }
139         }
140 
141         return requestedSessionId;
142     }
143 
144     public HttpSession getSession(boolean create) {
145 
146         HttpSession httpSession;
147 
148         if (isHttpSessions()) {
149             httpSession = super.getSession(false);
150             if (httpSession == null && create) {
151                 //Shiro 1.2: assert that creation is enabled (SHIRO-266):
152                 if (WebUtils.isSessionCreationEnabled(this)) {
153                     httpSession = super.getSession(create);
154                 } else {
155                     throw newNoSessionCreationException();
156                 }
157             }
158         } else {
159             boolean existing = getSubject().getSession(false) != null;
160 
161             if (this.session == null || !existing) {
162                 Session shiroSession = getSubject().getSession(create);
163                 if (shiroSession != null) {
164                     this.session = new ShiroHttpSession(shiroSession, this, this.servletContext);
165                 } else if (this.session != null) {
166                     this.session = null;
167                 }
168                 if (shiroSession != null && !existing) {
169                     setAttribute(REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
170                 }
171             }
172             httpSession = this.session;
173         }
174 
175         return httpSession;
176     }
177 
178     /**
179      * Constructs and returns a {@link DisabledSessionException} with an appropriate message explaining why
180      * session creation has been disabled.
181      *
182      * @return a new DisabledSessionException with appropriate no creation message
183      * @since 1.2
184      */
185     private DisabledSessionException newNoSessionCreationException() {
186         String msg = "Session creation has been disabled for the current request.  This exception indicates "
187                 + "that there is either a programming error (using a session when it should never be "
188                 + "used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created "
189                 + "for the current request.  See the " + DisabledSessionException.class.getName() + " JavaDoc "
190                 + "for more.";
191         return new DisabledSessionException(msg);
192     }
193 
194     public HttpSession getSession() {
195         return getSession(true);
196     }
197 
198     public boolean isRequestedSessionIdValid() {
199         if (isHttpSessions()) {
200             return super.isRequestedSessionIdValid();
201         } else {
202             Boolean value = (Boolean) getAttribute(REFERENCED_SESSION_ID_IS_VALID);
203             return (value != null && value.equals(Boolean.TRUE));
204         }
205     }
206 
207     public boolean isRequestedSessionIdFromCookie() {
208         if (isHttpSessions()) {
209             return super.isRequestedSessionIdFromCookie();
210         } else {
211             String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
212             return value != null && value.equals(COOKIE_SESSION_ID_SOURCE);
213         }
214     }
215 
216     public boolean isRequestedSessionIdFromURL() {
217         if (isHttpSessions()) {
218             return super.isRequestedSessionIdFromURL();
219         } else {
220             String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
221             return value != null && value.equals(URL_SESSION_ID_SOURCE);
222         }
223     }
224 
225     @Deprecated
226     public boolean isRequestedSessionIdFromUrl() {
227         return isRequestedSessionIdFromURL();
228     }
229 
230     private class ObjectPrincipal implements java.security.Principal {
231         private Object object;
232 
233         ObjectPrincipal(Object object) {
234             this.object = object;
235         }
236 
237         public Object getObject() {
238             return object;
239         }
240 
241         public String getName() {
242             return getObject().toString();
243         }
244 
245         public int hashCode() {
246             return object.hashCode();
247         }
248 
249         public boolean equals(Object o) {
250             if (o instanceof ObjectPrincipal) {
251                 ObjectPrincipal op = (ObjectPrincipal) o;
252                 return getObject().equals(op.getObject());
253             }
254             return false;
255         }
256 
257         public String toString() {
258             return object.toString();
259         }
260     }
261 }