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.session; 020 021import org.apache.shiro.session.InvalidSessionException; 022import org.apache.shiro.session.Session; 023import org.apache.shiro.util.StringUtils; 024import org.apache.shiro.web.servlet.ShiroHttpSession; 025 026import javax.servlet.http.HttpSession; 027import java.io.Serializable; 028import java.util.ArrayList; 029import java.util.Collection; 030import java.util.Date; 031import java.util.Enumeration; 032 033/** 034 * {@link Session Session} implementation that is backed entirely by a standard servlet container 035 * {@link HttpSession HttpSession} instance. It does not interact with any of Shiro's session-related components 036 * {@code SessionManager}, {@code SecurityManager}, etc, and instead satisfies all method implementations by interacting 037 * with a servlet container provided {@link HttpSession HttpSession} instance. 038 * 039 * @since 1.0 040 */ 041public class HttpServletSession implements Session { 042 043 private static final String HOST_SESSION_KEY = HttpServletSession.class.getName() + ".HOST_SESSION_KEY"; 044 private static final String TOUCH_OBJECT_SESSION_KEY = HttpServletSession.class.getName() + ".TOUCH_OBJECT_SESSION_KEY"; 045 046 private HttpSession httpSession = null; 047 048 public HttpServletSession(HttpSession httpSession, String host) { 049 if (httpSession == null) { 050 String msg = "HttpSession constructor argument cannot be null."; 051 throw new IllegalArgumentException(msg); 052 } 053 if (httpSession instanceof ShiroHttpSession) { 054 String msg = "HttpSession constructor argument cannot be an instance of ShiroHttpSession. This " + 055 "is enforced to prevent circular dependencies and infinite loops."; 056 throw new IllegalArgumentException(msg); 057 } 058 this.httpSession = httpSession; 059 if (StringUtils.hasText(host)) { 060 setHost(host); 061 } 062 } 063 064 public Serializable getId() { 065 return httpSession.getId(); 066 } 067 068 public Date getStartTimestamp() { 069 return new Date(httpSession.getCreationTime()); 070 } 071 072 public Date getLastAccessTime() { 073 return new Date(httpSession.getLastAccessedTime()); 074 } 075 076 public long getTimeout() throws InvalidSessionException { 077 try { 078 return httpSession.getMaxInactiveInterval() * 1000L; 079 } catch (Exception e) { 080 throw new InvalidSessionException(e); 081 } 082 } 083 084 public void setTimeout(long maxIdleTimeInMillis) throws InvalidSessionException { 085 try { 086 int timeout = Long.valueOf(maxIdleTimeInMillis / 1000).intValue(); 087 httpSession.setMaxInactiveInterval(timeout); 088 } catch (Exception e) { 089 throw new InvalidSessionException(e); 090 } 091 } 092 093 protected void setHost(String host) { 094 setAttribute(HOST_SESSION_KEY, host); 095 } 096 097 public String getHost() { 098 return (String) getAttribute(HOST_SESSION_KEY); 099 } 100 101 public void touch() throws InvalidSessionException { 102 //just manipulate the session to update the access time: 103 try { 104 httpSession.setAttribute(TOUCH_OBJECT_SESSION_KEY, TOUCH_OBJECT_SESSION_KEY); 105 httpSession.removeAttribute(TOUCH_OBJECT_SESSION_KEY); 106 } catch (Exception e) { 107 throw new InvalidSessionException(e); 108 } 109 } 110 111 public void stop() throws InvalidSessionException { 112 try { 113 httpSession.invalidate(); 114 } catch (Exception e) { 115 throw new InvalidSessionException(e); 116 } 117 } 118 119 public Collection<Object> getAttributeKeys() throws InvalidSessionException { 120 try { 121 Enumeration namesEnum = httpSession.getAttributeNames(); 122 Collection<Object> keys = null; 123 if (namesEnum != null) { 124 keys = new ArrayList<Object>(); 125 while (namesEnum.hasMoreElements()) { 126 keys.add(namesEnum.nextElement()); 127 } 128 } 129 return keys; 130 } catch (Exception e) { 131 throw new InvalidSessionException(e); 132 } 133 } 134 135 private static String assertString(Object key) { 136 if (!(key instanceof String)) { 137 String msg = "HttpSession based implementations of the Shiro Session interface requires attribute keys " + 138 "to be String objects. The HttpSession class does not support anything other than String keys."; 139 throw new IllegalArgumentException(msg); 140 } 141 return (String) key; 142 } 143 144 public Object getAttribute(Object key) throws InvalidSessionException { 145 try { 146 return httpSession.getAttribute(assertString(key)); 147 } catch (Exception e) { 148 throw new InvalidSessionException(e); 149 } 150 } 151 152 public void setAttribute(Object key, Object value) throws InvalidSessionException { 153 try { 154 httpSession.setAttribute(assertString(key), value); 155 } catch (Exception e) { 156 throw new InvalidSessionException(e); 157 } 158 } 159 160 public Object removeAttribute(Object key) throws InvalidSessionException { 161 try { 162 String sKey = assertString(key); 163 Object removed = httpSession.getAttribute(sKey); 164 httpSession.removeAttribute(sKey); 165 return removed; 166 } catch (Exception e) { 167 throw new InvalidSessionException(e); 168 } 169 } 170}