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 */ 019package org.apache.shiro.web.servlet; 020 021import org.apache.shiro.SecurityUtils; 022import org.apache.shiro.session.Session; 023import org.apache.shiro.subject.Subject; 024import org.apache.shiro.subject.support.DisabledSessionException; 025import org.apache.shiro.web.util.WebUtils; 026 027import javax.servlet.ServletContext; 028import javax.servlet.http.HttpServletRequest; 029import javax.servlet.http.HttpServletRequestWrapper; 030import javax.servlet.http.HttpSession; 031import java.security.Principal; 032 033 034/** 035 * A {@code ShiroHttpServletRequest} wraps the Servlet container's original {@code ServletRequest} instance, but ensures 036 * that all {@link HttpServletRequest} invocations that require Shiro's support ({@link #getRemoteUser getRemoteUser}, 037 * {@link #getSession getSession}, etc) can be executed first by Shiro as necessary before allowing the underlying 038 * Servlet container instance's method to be invoked. 039 * 040 * @since 0.2 041 */ 042public class ShiroHttpServletRequest extends HttpServletRequestWrapper { 043 044 //TODO - complete JavaDoc 045 046 //The following 7 constants support the Shiro's implementation of the Servlet Specification 047 public static final String COOKIE_SESSION_ID_SOURCE = "cookie"; 048 public static final String URL_SESSION_ID_SOURCE = "url"; 049 public static final String REFERENCED_SESSION_ID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID"; 050 public static final String REFERENCED_SESSION_ID_IS_VALID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID_VALID"; 051 public static final String REFERENCED_SESSION_IS_NEW = ShiroHttpServletRequest.class.getName() + "_REFERENCED_SESSION_IS_NEW"; 052 public static final String REFERENCED_SESSION_ID_SOURCE = ShiroHttpServletRequest.class.getName() + "REFERENCED_SESSION_ID_SOURCE"; 053 public static final String IDENTITY_REMOVED_KEY = ShiroHttpServletRequest.class.getName() + "_IDENTITY_REMOVED_KEY"; 054 public static final String SESSION_ID_URL_REWRITING_ENABLED = ShiroHttpServletRequest.class.getName() + "_SESSION_ID_URL_REWRITING_ENABLED"; 055 056 protected ServletContext servletContext = null; 057 058 protected HttpSession session = null; 059 protected boolean httpSessions = true; 060 061 public ShiroHttpServletRequest(HttpServletRequest wrapped, ServletContext servletContext, boolean httpSessions) { 062 super(wrapped); 063 this.servletContext = servletContext; 064 this.httpSessions = httpSessions; 065 } 066 067 public boolean isHttpSessions() { 068 return httpSessions; 069 } 070 071 public String getRemoteUser() { 072 String remoteUser; 073 Object scPrincipal = getSubjectPrincipal(); 074 if (scPrincipal != null) { 075 if (scPrincipal instanceof String) { 076 return (String) scPrincipal; 077 } else if (scPrincipal instanceof Principal) { 078 remoteUser = ((Principal) scPrincipal).getName(); 079 } else { 080 remoteUser = scPrincipal.toString(); 081 } 082 } else { 083 remoteUser = super.getRemoteUser(); 084 } 085 return remoteUser; 086 } 087 088 protected Subject getSubject() { 089 return SecurityUtils.getSubject(); 090 } 091 092 protected Object getSubjectPrincipal() { 093 Object userPrincipal = null; 094 Subject subject = getSubject(); 095 if (subject != null) { 096 userPrincipal = subject.getPrincipal(); 097 } 098 return userPrincipal; 099 } 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}