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    }