Hi All,
I've dug a little deeper and I see the problem - not sure what to do
about it, though. Maybe someone on the list will have a good idea or
this will help someone who runs into this problem in the future.
I have a RESTlet application which is protected by Shiro. Another
program POSTs to the RESTlet App to create/update resources. However,
this POSTer program creates a new connection every time it POSTs, so it
never has a Session ID.
Shiro, however, checks for a session ID (even under the Anonymous
filter). First it checks the cookies, then it checks the URL and
lastly, if and only if it is a POST, it will read the content looking
for the Session ID.
This is what causes my problem. After it has read the content, my
application Resource tries to read the content from the stream, but
can't since the stream's content has already been consumed.
Unfortunately, the stream doesn't support reset().
Is there a way to tell Shiro not to read a POST's content? I'm not
concerned about tracking the POSTer application with a Session ID,
although that is an option.
The determination to read the POST content is made in
org.apache.shiro.web.session.mgt.DefaultWebSessionManager.getReferencedSessionId(...)
by looking at the value of
org.apache.catalina.connector.Connector.parseBodyMethodsSet.
I could override DefaultWebSessionManager, I suppose, but that is not my
first choice and I'm unsure what that might break (logins?).
Thanks for any suggestions.
Sincerely,
Stephen McCants
On 7/26/2013 1:21 PM, Stephen McCants wrote:
Hello All,
I'm using Shiro to ensure that only authorized people can performs
POSTs on my RESTlet application. Unfortunately, I've run into a
strange problem. If I run without Shiro and my application handles
the POSTs correctly. However, if I put Shiro in place the content of
the POST (XML in this case) becomes unreadable. To try and simplify
the problem, I even set Shiro to use the anonymous filter, but it
still fails.
Here is the error I'm receiving when I try to parse the incoming XML:
Caused by: java.io.IOException: Couldn't read the XML representation.
Premature end of file.
at
org.restlet.ext.xml.DomRepresentation.getDocument(DomRepresentation.java:175)
at
org.restlet.ext.xml.XmlRepresentation.evaluate(XmlRepresentation.java:273)
at
org.restlet.ext.xml.XmlRepresentation.internalEval(XmlRepresentation.java:555)
... 81 more
Here is my shiro.ini:
[main]
# Take 2 on a shared cache/Single Sign On that can be used by both
REST and Schedule.
# Based on F_A_V's instructions from here:
#
http://shiro-user.582556.n2.nabble.com/Shiro-and-multiple-wars-within-the-same-Servlet-Container-td5560737.html
# Cache for single sign on
ssoCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
ssoCacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $ssoCacheManager
# DAO for single sign on
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager =
org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager
#
https://cwiki.apache.org/confluence/display/SHIRO/Session+Management#SessionManagement-SessionTimeout
# this sets up the session purge. Sessions inactive for over an hour will
# be purged from the database. the interval is set in milliseconds.
sessionValidationScheduler =
org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
sessionValidationScheduler.interval = 60000
sessionValidationScheduler.sessionManager = $sessionManager
securityManager.sessionManager.sessionValidationScheduler =
$sessionValidationScheduler
securityManager.sessionManager.sessionValidationSchedulerEnabled = true
# cookie for single sign on
# this sets up the session cookie. the name is the cookie name
# and the path is the cookie path. by setting the path to / we
# can use it across domains. ajax will automatically pick it up
# from the browser and send it with all calls to REST.
# using the default session name JSESSIONID but anything can
# be used.
cookie = org.apache.shiro.web.servlet.SimpleCookie
cookie.name = JSESSIONID
cookie.path = /
securityManager.sessionManager.sessionIdCookie = $cookie
# authc is the form based authentication filter from shiro
# the usernameParam and passwordParam below specify that the
# form submitted will have will have inputs of those names
# the login url is the login page.
# If the login attempt fails, the resulting AuthenticationException fully
# qualified class name will be set as a request attribute under the
failureKeyAttribute key.
# This can be used as an i18n key or lookup mechanism to explain to
the user
# why their login attempt failed (e.g. no account, incorrect password,
etc).
authc.usernameParam = j_username
authc.passwordParam = j_password
authc.loginUrl = /schedule_dev/login.jsp
#authc.successUrl = /index.html
authc.failureKeyAttribute = shiroLoginFailure
# Logout filter configuration (b/c it sends us off the bad places)
logout.redirectUrl = /schedule_dev/login.jsp?logout=true
# This is the connection information to the datbase
# that will be used for authentication. Where
# the user names and passwords are stored.
# TODO move this OUT of the shiro.ini so that it isn't part of the WAR
file. (WTL-141)
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.serverName = localhost
ds.user = root
ds.password = XXXXX
ds.databaseName = webtl
# the authenticationQuery is the sql used to get the password from the
db.
#jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm = com.hcs.webtl.shiro.realm.WebTimelineJdbcRealm
jdbcRealm.dataSource = $ds
jdbcRealm.authenticationQuery = SELECT password FROM webtl.users where
email_address = ?
# all passwords are in the clear now but probably should be encrypted.
# this is the start of that effort.
#sha256Matcher =
org.apache.shiro.authc.credential.Sha256CredentialsMatcher
#jdbcRealm.credentialsMatcher = $sha256Matcher
[urls]
/** = anon
Below is my web.xml that sets Shiro up:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>XXXXXX</display-name>
<!-- Restlet Application -->
<context-param>
<param-name>org.restlet.application</param-name>
<param-value>
com.hcs.webtl.rest.MainApplication
</param-value>
</context-param>
<!-- Big Memory Go license file for EH Cache -->
<context-param>
<param-name>com.tc.productkey.path</param-name>
<param-value>terracotta-license.key</param-value>
</context-param>
<!-- Restlet Adapter -->
<servlet>
<servlet-name>ServerServlet</servlet-name>
<servlet-class>
org.restlet.ext.servlet.ServerServlet
</servlet-class>
</servlet>
<!-- Catch all requests -->
<servlet-mapping>
<servlet-name>ServerServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Shriro security setup -->
<!-- no init-param means load the INI config from
classpath:shiro.ini -->
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<!-- no init-param means load the INI config from
classpath:shiro.ini -->
<filter>
<filter-name>securityFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<!-- Initialize data cleanup listener -->
<listener>
<listener-class>com.hcs.data.background.BackgroundContextListener</listener-class>
</listener>
</web-app>
I could post my ehcache.xml, but I don't think it matters here.
Any thoughts? I'm still trying to debug it, but I'm at a bit of a loss.
Thanks in advance!
Sincerely,
Stephen McCants
--
Stephen McCants
Senior Software Engineer
Healthcare Control Systems
1-877-877-8795 x116