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 */ 042@SuppressWarnings({"checkstyle:JavadocVariable"}) 043public class ShiroHttpServletRequest extends HttpServletRequestWrapper { 044 045 //The following 7 constants support the Shiro's implementation of the Servlet Specification 046 public static final String COOKIE_SESSION_ID_SOURCE = "cookie"; 047 public static final String URL_SESSION_ID_SOURCE = "url"; 048 public static final String REFERENCED_SESSION_ID = ShiroHttpServletRequest.class.getName() 049 + "_REQUESTED_SESSION_ID"; 050 public static final String REFERENCED_SESSION_ID_IS_VALID = ShiroHttpServletRequest.class.getName() 051 + "_REQUESTED_SESSION_ID_VALID"; 052 public static final String REFERENCED_SESSION_IS_NEW = ShiroHttpServletRequest.class.getName() 053 + "_REFERENCED_SESSION_IS_NEW"; 054 public static final String REFERENCED_SESSION_ID_SOURCE = ShiroHttpServletRequest.class.getName() 055 + "REFERENCED_SESSION_ID_SOURCE"; 056 public static final String IDENTITY_REMOVED_KEY = ShiroHttpServletRequest.class.getName() 057 + "_IDENTITY_REMOVED_KEY"; 058 public static final String SESSION_ID_URL_REWRITING_ENABLED = ShiroHttpServletRequest.class.getName() 059 + "_SESSION_ID_URL_REWRITING_ENABLED"; 060 061 protected ServletContext servletContext; 062 063 protected HttpSession session; 064 protected boolean httpSessions; 065 066 public ShiroHttpServletRequest(HttpServletRequest wrapped, ServletContext servletContext, boolean httpSessions) { 067 super(wrapped); 068 this.servletContext = servletContext; 069 this.httpSessions = httpSessions; 070 } 071 072 public boolean isHttpSessions() { 073 return httpSessions; 074 } 075 076 public String getRemoteUser() { 077 String remoteUser; 078 Object scPrincipal = getSubjectPrincipal(); 079 if (scPrincipal != null) { 080 if (scPrincipal instanceof String) { 081 return (String) scPrincipal; 082 } else if (scPrincipal instanceof Principal) { 083 remoteUser = ((Principal) scPrincipal).getName(); 084 } else { 085 remoteUser = scPrincipal.toString(); 086 } 087 } else { 088 remoteUser = super.getRemoteUser(); 089 } 090 return remoteUser; 091 } 092 093 protected Subject getSubject() { 094 return SecurityUtils.getSubject(); 095 } 096 097 protected Object getSubjectPrincipal() { 098 Object userPrincipal = null; 099 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}