Atmosphere websocket disconnected by Tomcat8 - tomcat8

As my Apache Tomcat Server (8.0.39) has session timeout at 30 minutes (set in web.xml), I can't seem to get Atmosphere configured right to stop the webocket being disconnected after 30 minutes. Using runtime 2.4.8 and Javascript 2.3.5.
The message I get is:
Websocket closed, reason: This connection was established under an
authenticated HTTP session that has ended. - wasClean: true
Atmosphere: Firing onClose (closed case)
reasonPhrase:"maxReconnectOnClose reached"
I am using both client and server heartbeats. The server sends the heartbeat every 60 seconds, but this does not stop the Tomcat session from timing out at 30 minutes.
I've tried using MAX_INACTIVITY as outlined here:
https://github.com/Atmosphere/atmosphere/issues/2250
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>o.a.interceptor.IdleResourceInterceptor</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.session.maxInactiveInterval</param-name>
<param-value>3600000</param-value>
</init-param>
<init-param>
<param-name>o.a.cpr.CometSupport.maxInactiveActivity</param-name>
<param-value>3600000</param-value>
</init-param>
But this is ignored as well and Tomcat closes the websocket.
Is there some way in Atmosphere to touch the Http Session and stop it from closing my websockets?
Basic setup:
#WebSocketHandlerService(path = "/async/chat", broadcasterCache =
UUIDBroadcasterCache.class)
public class ChatServer extends WebSocketHandlerAdapter {}
Javascript:
request.url = 'async/chat';
request.contentType = 'application/json';
request.transport = 'websocket';
request.fallbackTransport = 'websocket';
request.maxReconnectOnClose = 5;
request.enableProtocol = true;
request.trackMessageLength = true;
request.timeout = 3600000;
request.logLevel = 'debug';
web.xml:
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<init-param>
<param-name>org.atmosphere.cpr.packages</param-name>
<param-value>atnf.jportal.websocket</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>o.a.client.TrackMessageSizeInterceptor</param-value>
</init-param>
<init-param>
<param-name>
o.a.i.HeartbeatInterceptor.clientHeartbeatFrequencyInSeconds
</param-name>
<param-value>120</param-value>
</init-param>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/async/*</url-pattern>
</servlet-mapping>

By default, the Tomcat installation closed all sessions after a 30 minute period. With the atmosphere websocket implementation, this timeout will also cause all websockets to close, even though the client/server sends a heartbeat using HeartbeatInterceptor.
A mitigation plan was to simply set all sessions to have an infinite timeout in the application web.xml file, but this leaves stale sessions, which can number in the hundreds if not managed manually. After a bit of digging, it seems one can configure atmosphere to set session max inactive interval to -1 when an atmosphere connection exists.
In web.xml:
<init-param>
<param-name>org.atmosphere.cpr.removeSessionTimeout</param-name>
<param-value>true</param-value>
</init-param>
By itself, this does not enable sessions to have an infinite timeout, you also have to enable the listener
<listener>
<listener-class>org.atmosphere.cpr.SessionSupport</listener-class>
</listener>
With the above enabled, each session is assigned the following attribute/properties:
name: atmosphere.session.timeout.restorer
type: org.atmosphere.cpr.SessionTimeoutRestorer
value: SessionTimeoutRestorer[timeout=1800, requestCount=4]
Logging out of the application removes this attribute and assigns a timeout (30min tomcat default setting) to the remaining session*.
Spring Security closes the existing session and creates a new one (with timeout enabled).

Related

Why doesn't Apache Shiro's [anon] Filter work correctly?

I tried to use authentication with Apache Shiro on my project, but without succes. I can't discover where is the trouble. I need only that whoever user access the page /pages/principal/products.xhtml directly, choose the product to buy and then be redirect to /purchase.xhtml to finish the purchase, but in my case all requests that I try are redirect to /login.xhtml page. Does anyone have any suggestions? code below. thanks!
shiro.ini
[main]
authc.loginUrl = /login.xhtml
authc.successUrl = /index.xhtml
[users]
admin#faces.com = adminfaces, admin
user#faces.com = user, customer
[roles]
admin = *
customer = purchases
[urls]
/index.xhtml = anon
/pages/principal/products = anon
/login.xhtml = authc
/javax.faces.resource/** = anon
/logout = logout
/pages/purchase/** = authc
/protected/** = authc, roles[admin]
web.xml
...
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
...
My guess is you need to change the line:
/pages/principal/products = anon to /pages/principal/products.xhtml = anon
You might also be able to use permissive filter too
I was able to solve my trouble. I'm using now redhat PicketLink solution. It's uses a fluent java language to configure paths to secure and it has a lower learnig curve. I'm considering Apache Shiro a great API for security, but I have a little time to learn it. thanks for your helps #Brian Demers.

Wildfly - Problems with form based authentication after restart

We have what I believe to be a pretty standard form based authentication for a web application running on wildfly 8.2.
The authentication works well, except that when we stop&start the server some users are unable to log in again.
I have managed to reproduce one variant of this:
If I open the login page, /xxxx/app, before I restart, and then try to log in after the server is up again, I end up on a blank /xxxx/j_security_check page.
In my logs I can see that the actual authentication is run OK.
If I have understood this j_security_check mechanism properly, it goes something like this:
I access /xxxx/app
Wildfly sees that this url requires authentication. It remembers it and forwards me to login.jsp.
When I submit my login form to the magical j_security_check address it replaces it with the remembered /xxxx/app address.
If this is conceptually correct, I can see that a restart can be troublesome; The web server no longer remembers the /xxxx/app address and doesn't know where to redirect me to.
Does anyone have a workaround for this problem?
Any way to give wildfly a default page to go to after j_security_check?
Edit: I found this one: It is probably the same underlying cause:
Jboss Wildfly 8.1 session timeout on login page
jboss-web.xml:
<jboss-web>
<security-domain>ptsmc</security-domain>
<default-encoding>UTF-8</default-encoding>
</jboss-web>
web.xml:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
<!-- -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<security-constraint>
<display-name>ptsmc</display-name>
<web-resource-collection>
<web-resource-name>ptsmc</web-resource-name>
<url-pattern>/app/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>WEB</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>
<security-role>
<description>Users must have this role to be granted access to Application</description>
<role-name>WEB</role-name>
</security-role>
login.jsp:
<form name="login_form" method="POST" action="<%=response.encodeURL(request.getContextPath() + "/j_security_check")%>">
<table>
<tr><td>User id:</td><td><input type=text name=j_username autofocus onblur="this.value = this.value.toUpperCase();"></td></tr>
<tr><td>Password:</td><td><input type=password name=j_password></td></tr>
<tr><td> </td><td><input type=submit value="Submit"></td></tr>
</table>
</form>

Configuring Spring Security for X509 client authentication, it isn't prompting browser for certificate

I'm trying to enable an application to use Client-Auth security with spring. Here's my configuration:
<security:http pattern="/api/**" >
<security:x509 subject-principal-regex="CN=(.*?),"
user-service-ref="x509UserService" />
<security:intercept-url pattern="/api/**" access="IS_AUTHENTICATED_FULLY" requires-channel="https" />
</security:http>
If I don't configure anything within web.xml or tomcat's server.xml, the browser is never prompted to send along a certificate with the request. Consequently, it always return null in in org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.extractClientCertificate(HttpServletRequest) method.
Is there something special that needs to be configured to have Spring participate in the SSL flow and request the client certificate?
Any help would be appreciated.
If I specify clientAuth='want' in the server.xml connector configuration, this has the undesirable side-effect of prompting everyone for certificates regardless of if they're accessing the /api path.
Similarly, if I specify the login-config and auth-method to be CLIENT-CERT, it also challenges the user, but then I would basically have to duplicate all of the cert checking I'd be doing in spring (or so it would seem).
Depending on your current java and build variety, at the very minimum you would either need to include something similar to the
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
or if you're using Java configuration with spring...
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}

How to use HTTPS with Glassfish 4 and JSF 2.2?

Just for learning purposes, I want to use SSL in the application I have developed in my local environment.
So I want all my connections to go through ssl.
How can I implement this with Glassfish 4.0 ?
Here is an example of using JAAS Form authentication:
on web.xml this block of code defines what urls will be SSL enabled:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>userauth</realm-name>
<form-login-config>
<form-login-page>/login.jsf</form-login-page>
<form-error-page>/loginError.jsf</form-error-page>
</form-login-config>
</login-config>
<security-constraint>
<display-name>ConstraintSSL</display-name>
<web-resource-collection>
<web-resource-name>protected</web-resource-name>
<description/>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Now on your application server (glassfish) configure your authentication realm "userauth" in this example:
create-auth-realm --classname com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm
--property jaas-context=jdbcRealm:datasource-jndi=oracleXE10gJDBCResource:user-
table=TB_USER:user-name-column=ID_USER:password-column=PASSWORD:group-
table=TB_USER_GROUP_USER:group-name-column=ID_GROUP:group_table_user-name-
column=ID_GROUP:digest-algorithm=MD5 userauth
In this example I created a JDBC based realm with MD5 encrypted passwords on a User table called "TB_USER" along with the group table names. You might create your own authentication realm, it can be file, jdbc or other JAAS type (please see JAAS doc for each specific one).
Now any requests for your app shall be using SSL.
Glassfish will redirect to the SSL port (default 8181) and your browser will be displaying the default SSL Trust certificate alert window (in case you are using a self-signed certificate) asking if you trust the connection, and after accepting you should see the page rendered correctly in SSL mode - https
Navigate to Glassfish Admin Console and then Server Settings --> Network Listeners. There you can set the listeners to use SSL. By default there are three listeners, 4848 for admin console, 8080 for general http listening, and 8181 for secured http listening. There are several things you can do here
To enable SSL for listeners or edit Listener check Security option
To disable listeners uncheck
On SSL tab fill the SSL information

Unable to setup basic authentication with jdbc realm and Glassfish

I'm fighting with a Glassfish v3 and a very simple JAX-RS service (taken athttp://www.vogella.de/articles/REST/article.html
What I want to achieve is setup basic http authentication for all the resources. If wish when a user request http://localhost:8080/de.vogella.jersey.first/rest/hello, the browser popups an alert prompting for username+password.
I've decided to go for a JDBCRealm authentication. I use PostgreSQL 8.4 and the correct JDBC driver.
My problem is that the authentication doesn't seem to be active (the HTTP headers are very simple ones :
Request URL:http://localhost:8080/de.vogella.jersey.first/rest/hello
Request Method:GET
Status Code:200 OK
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie:JSESSIONID=ec48541dc7654806fcf022d79e66; treeForm:tree-hi=treeForm:tree:configuration:loggerSetting
Host:localhost:8080
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.187 Safari/535.1
Response Headers
Content-Type:text/html
Date:Fri, 07 Oct 2011 14:26:26 GMT
Server:GlassFish Server Open Source Edition 3.0.1
Transfer-Encoding:chunked
X-Powered-By:Servlet/3.0
The authentication is setup but seems inactive. At that point, I need your skills for analyzing what I've done wrong.
What I've done so far :
1/ Deployed the JAX-RS service (this works ok, see previous URL)
2/ Created a database, created two tables :
CREATE TABLE groups
(
username character varying(16) NOT NULL,
id character varying(20) NOT NULL,
CONSTRAINT groups_pkey PRIMARY KEY (username, id),
CONSTRAINT fk_username FOREIGN KEY (username)
REFERENCES users (username) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE TABLE users
(
username character varying(16) NOT NULL,
"password" character varying(32) NOT NULL,
CONSTRAINT users_pkey PRIMARY KEY (username)
);
and populated them as follow :
table "groups" -> "webuser";"employees"
table "users" -> "webuser";"webuser"
3/ In the Glassfish admin GUI,I added a Connect Pool called "postgres" as follow :
The additional properties are shown here :
4/ I then created a JDVC Resource called "postgres" as shown below :
5/ In the Glassfish admin GUI, I added a Security Realm, called "postgres", as shown below :
6/ I also set to "FINEST" the log level for javax.enterprise.system.core.security in the "Logger Settings".
After requesting the webservice from a browser, I get the following in the server.log file :
[#|2011-10-07T16:26:26.410+0200|FINE|glassfish3.0.1|javax.enterprise.system.core.security|_ThreadID=67;_ThreadName=Thread-1;ClassName=com.sun.enterprise.security.web.integration.WebSecurityManager;MethodName=setPolicyContext;|[Web-Security] Policy Context ID was: de.vogella.jersey.first/de_vogella_jersey_first|#]
[#|2011-10-07T16:26:26.412+0200|FINE|glassfish3.0.1|javax.enterprise.system.core.security.com.sun.enterprise.security|_ThreadID=67;_ThreadName=Thread-1;ClassName=com.sun.enterprise.security.SecurityContext;MethodName=setCurrentSecurityContext;|SecurityContext: setCurrentSecurityContext method called|#]
7/ Regarding the code, I didn't add any annotation, but I updated my web.xml as follow :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>de.vogella.jersey.first</display-name>
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>de.vogella.jersey.first</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>customer creation</web-resource-name>
<url-pattern>/rest/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>webusers</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>postgres</realm-name>
</login-config>
<security-role>
<role-name>webusers</role-name>
</security-role>
</web-app>
And the sun-web.xml as follow :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app error-url="">
<context-root>/de.vogella.jersey.first</context-root>
<security-role-mapping>
<role-name>webusers</role-name>
<group-name>webusers</group-name>
</security-role-mapping>
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class java code.</description>
</property>
</jsp-config>
</sun-web-app>
What is wrong with this ? Did I forgot anything ?
Thank you for your time !
I found out that I had to disable the "Keep session between deployments". This option can be found in the server, by double-clicking on the deployment server and unchecking the box.