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             if (this.session == null) {
155 
156                 boolean existing = getSubject().getSession(false) != null;
157 
158                 Session shiroSession = getSubject().getSession(create);
159                 if (shiroSession != null) {
160                     this.session = new ShiroHttpSession(shiroSession, this, this.servletContext);
161                     if (!existing) {
162                         setAttribute(REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
163                     }
164                 }
165             }
166             httpSession = this.session;
167         }
168 
169         return httpSession;
170     }
171 
172     /**
173      * Constructs and returns a {@link DisabledSessionException} with an appropriate message explaining why
174      * session creation has been disabled.
175      *
176      * @return a new DisabledSessionException with appropriate no creation message
177      * @since 1.2
178      */
179     private DisabledSessionException newNoSessionCreationException() {
180         String msg = "Session creation has been disabled for the current request.  This exception indicates " +
181                 "that there is either a programming error (using a session when it should never be " +
182                 "used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created " +
183                 "for the current request.  See the " + DisabledSessionException.class.getName() + " JavaDoc " +
184                 "for more.";
185         return new DisabledSessionException(msg);
186     }
187 
188     public HttpSession getSession() {
189         return getSession(true);
190     }
191 
192     public boolean isRequestedSessionIdValid() {
193         if (isHttpSessions()) {
194             return super.isRequestedSessionIdValid();
195         } else {
196             Boolean value = (Boolean) getAttribute(REFERENCED_SESSION_ID_IS_VALID);
197             return (value != null && value.equals(Boolean.TRUE));
198         }
199     }
200 
201     public boolean isRequestedSessionIdFromCookie() {
202         if (isHttpSessions()) {
203             return super.isRequestedSessionIdFromCookie();
204         } else {
205             String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
206             return value != null && value.equals(COOKIE_SESSION_ID_SOURCE);
207         }
208     }
209 
210     public boolean isRequestedSessionIdFromURL() {
211         if (isHttpSessions()) {
212             return super.isRequestedSessionIdFromURL();
213         } else {
214             String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
215             return value != null && value.equals(URL_SESSION_ID_SOURCE);
216         }
217     }
218 
219     public boolean isRequestedSessionIdFromUrl() {
220         return isRequestedSessionIdFromURL();
221     }
222 
223     private class ObjectPrincipal implements java.security.Principal {
224         private Object object = null;
225 
226         public ObjectPrincipal(Object object) {
227             this.object = object;
228         }
229 
230         public Object getObject() {
231             return object;
232         }
233 
234         public String getName() {
235             return getObject().toString();
236         }
237 
238         public int hashCode() {
239             return object.hashCode();
240         }
241 
242         public boolean equals(Object o) {
243             if (o instanceof ObjectPrincipal) {
244                 ObjectPrincipal op = (ObjectPrincipal) o;
245                 return getObject().equals(op.getObject());
246             }
247             return false;
248         }
249 
250         public String toString() {
251             return object.toString();
252         }
253     }
254 }