Commit 347923e9 authored by Matija Obreza's avatar Matija Obreza
Browse files

HTTP Sessions: Reduce the number of sessions created

- CSRF is the main culprit in JSP
parent 4abaaebf
/** /*
* Copyright 2015 Global Crop Diversity Trust * Copyright 2019 Global Crop Diversity Trust
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -12,36 +12,62 @@ ...@@ -12,36 +12,62 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ */
package org.genesys2.spring; package org.genesys2.spring;
import java.util.Arrays;
import javax.servlet.annotation.WebListener; import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener; import javax.servlet.http.HttpSessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Enable this {@link WebListener} to figure out what initates the HTTP Session. * Enable this {@link WebListener} to figure out what initates the HTTP Session.
* *
* <ul> * <ul>
* <li>init.jsp: session="false"</li> * <li>init.jsp: session="false"</li>
* <li>_csrf.getToken() then creates the session anyway in decorators -- this is * <li>_csrf.getToken() then creates the session anyway in decorators -- this is
* used for AJAX requests</li> * used for AJAX requests</li>
* </ul> * </ul>
*
* @author Matija Obreza
*/ */
// @WebListener @WebListener
public class WhoMakesTheJSessionId implements HttpSessionListener { public class WhoMakesTheJSessionId implements HttpSessionListener {
public static final Logger LOG = LoggerFactory.getLogger(WhoMakesTheJSessionId.class);
public WhoMakesTheJSessionId() { public WhoMakesTheJSessionId() {
System.err.println("WhoMakesTheJSessionId listener instantiated."); System.err.println("WhoMakesTheJSessionId listener instantiated.");
} }
@Override @Override
public void sessionCreated(HttpSessionEvent se) { public void sessionCreated(final HttpSessionEvent se) {
throw new UnsupportedOperationException("Sessions are not allowed"); LOG.warn("HTTP Session {} created", se.getSession().getId());
if (LOG.isTraceEnabled()) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
StringBuilder sb= new StringBuilder();
Arrays.stream(stackTrace).forEach((st) -> {
sb.append(Thread.currentThread().getName());
sb.append("\t");
sb.append(st.getClassName());
sb.append(":");
sb.append(st.getMethodName());
sb.append("(");
sb.append(st.getFileName());
sb.append(":");
sb.append(st.getLineNumber());
sb.append(")\n");
});
LOG.trace("Session {} created in:\n{}", se.getSession().getId(), sb.toString());
}
} }
@Override @Override
public void sessionDestroyed(HttpSessionEvent se) { public void sessionDestroyed(final HttpSessionEvent se) {
throw new UnsupportedOperationException("Sessions are not allowed"); LOG.warn("Session {} destroyed", se.getSession().getId());
} }
} }
\ No newline at end of file
...@@ -156,11 +156,11 @@ public class OAuth2ServerConfig { ...@@ -156,11 +156,11 @@ public class OAuth2ServerConfig {
// authorize everything on this path // authorize everything on this path
.authorizeRequests().antMatchers("/**").fullyAuthenticated() .authorizeRequests().antMatchers("/**").fullyAuthenticated()
// no sessions // no sessions
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().requestMatchers().antMatchers("/api/**", "/brapi/**") .and().requestMatchers().antMatchers("/api/**", "/brapi/**")
// no sessions // no sessions
.and().sessionManagement().disable() .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// no CSRF // no CSRF
.csrf().disable() .csrf().disable()
......
...@@ -25,6 +25,7 @@ import org.springframework.security.authentication.AuthenticationManager; ...@@ -25,6 +25,7 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
...@@ -57,7 +58,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -57,7 +58,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/*@formatter:off*/ /*@formatter:off*/
http http
// No JSESSIONID in URL // No JSESSIONID in URL
.sessionManagement().enableSessionUrlRewriting(false).sessionFixation().migrateSession() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).enableSessionUrlRewriting(false).sessionFixation().migrateSession()
// Authorizations // Authorizations
.and().authorizeRequests() .and().authorizeRequests()
......
...@@ -99,7 +99,3 @@ ...@@ -99,7 +99,3 @@
<!--/.nav-collapse --> <!--/.nav-collapse -->
</div> </div>
</nav> </nav>
<form id="logoutForm" action="/logout" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
...@@ -12,11 +12,6 @@ ...@@ -12,11 +12,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="language" content="${pageContext.response.locale.language}" /> <meta name="language" content="${pageContext.response.locale.language}" />
<!-- CSRF protection-->
<meta name="_csrf" content="${_csrf.token}" />
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}" />
<!-- Links --> <!-- Links -->
<link rel="shortcut icon" href="<c:url value="/html/1/images/genesys.png" />" /> <link rel="shortcut icon" href="<c:url value="/html/1/images/genesys.png" />" />
......
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" language="java" %> <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" language="java" session="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> <%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
......
...@@ -8,21 +8,7 @@ ...@@ -8,21 +8,7 @@
</a> </a>
<ul class="dropdown-menu pull-left"> <ul class="dropdown-menu pull-left">
<li> <li>
<form id="loginForm" role="form" method="post" action="<c:url value="/login-attempt" />"> <form id="loginForm" role="form" method="get" action="<c:url value="/login" />">
<div class="form-group">
<label class="pull-left" for="username"><spring:message code="login.username" /></label>
<input type="email" class="form-control" id="username" name="username" placeholder="<spring:message code="login.username"/>" />
</div>
<div class="form-group">
<label class="pull-left" for="password"><spring:message code="login.password" /></label>
<input type="password" class="form-control" id="password" name="password" placeholder="<spring:message code="login.password"/>" />
</div>
<div class="checkbox">
<label class="pull-left">
<input type="checkbox" name="_spring_security_remember_me" id="_spring_security_remember_me" />
<spring:message code="login.remember-me" />
</label>
</div>
<button type="submit" class="btn btn-primary"><spring:message code="login.login-button" /></button> <button type="submit" class="btn btn-primary"><spring:message code="login.login-button" /></button>
<span class="or">-</span> <span class="or">-</span>
<a href="<c:url value="/google/login" />" class="btn btn-default google-signin"> <a href="<c:url value="/google/login" />" class="btn btn-default google-signin">
...@@ -31,9 +17,7 @@ ...@@ -31,9 +17,7 @@
<a href="<c:url value="/registration" />" class="btn btn-default"> <a href="<c:url value="/registration" />" class="btn btn-default">
<spring:message code="login.register-now" /> <spring:message code="login.register-now" />
</a> </a>
<!-- CSRF protection --> </form>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</li> </li>
</ul> </ul>
</li> </li>
...@@ -33,5 +33,8 @@ ...@@ -33,5 +33,8 @@
</li> </li>
</security:authorize> </security:authorize>
</ul> </ul>
</li> </li>
<form id="logoutForm" action="/logout" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</security:authorize> </security:authorize>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment