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