Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #sabi-113 (#152) #153

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# History of changes (since 5/2022)

## Release 1.2.5

### Bugfixes
* HTTP.500 in some cases for returing users with timedout session (sabi-113)

## Release 1.2.4

### Bugfixes
Expand Down
40 changes: 4 additions & 36 deletions sabi-webclient/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<groupId>de.bluewhale</groupId>
<artifactId>sabi-webclient</artifactId>
<version>1.2.4</version>
<version>1.2.5</version>
<packaging>jar</packaging>
<name>sabi-webclient</name>
<description>A JSF based webclient for sabi.</description>
Expand Down Expand Up @@ -47,7 +47,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.7</version>
<version>3.2.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

Expand All @@ -57,8 +57,8 @@
<java.version>21</java.version>
<log4j2.version>2.20.0</log4j2.version>
<jakarta.cdi.version>4.0.1</jakarta.cdi.version>
<micrometer.prometheus.version>1.12.2</micrometer.prometheus.version>
<joinfaces.version>5.1.4</joinfaces.version>
<micrometer.prometheus.version>1.12.3</micrometer.prometheus.version>
<joinfaces.version>5.2.2</joinfaces.version>
<sabi.boundary.version>1.2.5</sabi.boundary.version>
<passay.version>1.6.4</passay.version>
<owasp.plugin.version>9.0.9</owasp.plugin.version>
Expand Down Expand Up @@ -107,11 +107,6 @@
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
Expand Down Expand Up @@ -215,22 +210,6 @@

<build>
<finalName>sabi-webclient</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.joinfaces</groupId>
<artifactId>joinfaces-maven-plugin</artifactId>
<version>${joinfaces.version}</version>
<executions>
<execution>
<goals>
<goal>classpath-scan</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
Expand Down Expand Up @@ -276,17 +255,6 @@
</executions>
</plugin>

<plugin>
<!--
Description from: https://docs.joinfaces.org/current/reference/
JoinFaces provides org.joinfaces:joinfaces-maven-plugin Maven plugin
to configure a classpath scan at build-time in order to reduce the
startup time of applications which use an embedded servlet container.
-->
<groupId>org.joinfaces</groupId>
<artifactId>joinfaces-maven-plugin</artifactId>
</plugin>

<plugin>
<!-- Used for vulnerability checks
The examples below can be executed using mvn verify.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 by Stefan Schubert under the MIT License (MIT).
* Copyright (c) 2024 by Stefan Schubert under the MIT License (MIT).
* See project LICENSE file for the detailed terms and conditions.
*/

Expand All @@ -8,16 +8,20 @@
import de.bluewhale.sabi.webclient.utils.I18nUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.servlet.http.Cookie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.context.annotation.SessionScope;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

/**
* Container for mandatory things which we need to keep in a user session.
Expand Down Expand Up @@ -170,8 +174,24 @@ public void setLanguage(String language) {

/** Invalidates Frontend Session in case of logout. */
public void endSession(){

// On the Serverside
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().invalidateSession();
ExternalContext externalContext = context.getExternalContext();
externalContext.invalidateSession();

// And on the Client Side. Otherwise the cookies there
// might survive and we may observe a HTTP-500
// in combination with a server restart, see sabi-113 for details.
// Löschen der Cookies
Map<String, Object> cookies = externalContext.getRequestCookieMap();
Iterator<String> iterator = cookies.keySet().iterator();
while (iterator.hasNext()) {
String cookieName = iterator.next();
Cookie cookie = (Cookie) cookies.get(cookieName);
cookie.setMaxAge(0); // By setting the expiration "date" to 0, the cookie is being invalidates by the browser.
externalContext.addResponseCookie(cookieName, null, null);
}
}

@PostConstruct
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 by Stefan Schubert under the MIT License (MIT).
* Copyright (c) 2024 by Stefan Schubert under the MIT License (MIT).
* See project LICENSE file for the detailed terms and conditions.
*/

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
/*
* Copyright (c) 2023 by Stefan Schubert under the MIT License (MIT).
* Copyright (c) 2024 by Stefan Schubert under the MIT License (MIT).
* See project LICENSE file for the detailed terms and conditions.
*/

package de.bluewhale.sabi.webclient.config;

import de.bluewhale.sabi.webclient.security.CustomExceptionHandlerFilter;
import de.bluewhale.sabi.webclient.security.SabiDoorKeeper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;

Expand All @@ -31,12 +33,17 @@ public class WebSecurityConfig {
@Autowired
SabiDoorKeeper sabiAuthenticationProvider;

@Autowired
private CustomExceptionHandlerFilter customExceptionHandlerFilter;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {

MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);

http
// Add our sabi-113 required exception handler here
.addFilterAfter(customExceptionHandlerFilter, FilterSecurityInterceptor.class)
.authorizeRequests(authorize -> authorize
.requestMatchers(mvcMatcherBuilder.pattern("/jakarta.faces.resource/**")).permitAll()
// Allow Pages that don't require an auth context.
Expand All @@ -50,8 +57,10 @@ public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospe
.requestMatchers(mvcMatcherBuilder.pattern( "/logout.xhtml")).permitAll()
.requestMatchers(mvcMatcherBuilder.pattern( "/sessionExpired.xhtml")).permitAll()
.requestMatchers(mvcMatcherBuilder.pattern( "/credits.xhtml")).permitAll()
.requestMatchers(mvcMatcherBuilder.pattern( "/static/**")).permitAll()
.requestMatchers(mvcMatcherBuilder.pattern( "/static/error/**")).permitAll()
.requestMatchers(mvcMatcherBuilder.pattern( "/.well-known/**")).permitAll()
.requestMatchers(mvcMatcherBuilder.pattern( "/error")).permitAll() // Error Controller
.requestMatchers(mvcMatcherBuilder.pattern( "/images/**")).permitAll() // Error Controller
// Allow Monitoring Endpoint
.requestMatchers(mvcMatcherBuilder.pattern(HttpMethod.GET, "/actuator/**")).permitAll()
// all others require authentication
Expand All @@ -61,7 +70,7 @@ public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospe

// In Case of a session timeout don't go directly to the login page,
// use this page instead, for being able to notify the user what has happened.

.sessionManagement(session -> session.invalidSessionUrl("/sessionExpired.xhtml"))

// login - using this the browser redirect to this page if login is required and you are not logged in.
Expand All @@ -76,7 +85,8 @@ public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospe
.authenticationProvider(this.sabiAuthenticationProvider)

// not needed as JSF 2.2 is implicitly protected against CSRF
.csrf(csrf -> csrf.disable());
.csrf(csrf -> csrf.disable())
;

return http.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import java.util.List;
import java.util.Locale;

import static de.bluewhale.sabi.webclient.utils.PageRegister.MEASUREMENT_VIEW_PAGE;

/**
* Controller for the Measurement View as shown in measureView.xhtml
*
Expand All @@ -39,7 +41,6 @@
@Getter
public class MeasurementListView extends AbstractControllerTools implements Serializable {

private static final String MEASUREMENT_VIEW_PAGE = "measureView";
private static final int MAX_RESULT_COUNT = 5;

@Autowired
Expand Down Expand Up @@ -119,7 +120,7 @@ public String getTankNameForId(Long tankId) {

public String resetForm() {
measurement = new MeasurementTo();
return MEASUREMENT_VIEW_PAGE;
return MEASUREMENT_VIEW_PAGE.getNavigationableAddress();
}

public String save() {
Expand All @@ -135,7 +136,7 @@ public String save() {
} else {
MessageUtil.warn("troubleMsg", "common.incompleted_formdata.t", userSession.getLocale());
}
return MEASUREMENT_VIEW_PAGE;
return MEASUREMENT_VIEW_PAGE.getNavigationableAddress();
}

private boolean allDataProvided(MeasurementTo measurement) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 by Stefan Schubert under the MIT License (MIT).
* Copyright (c) 2024 by Stefan Schubert under the MIT License (MIT).
* See project LICENSE file for the detailed terms and conditions.
*/

Expand All @@ -9,6 +9,8 @@
import jakarta.inject.Named;
import lombok.extern.slf4j.Slf4j;

import static de.bluewhale.sabi.webclient.utils.PageRegister.LOGOUT_PAGE;

/**
* MenuActions
*
Expand All @@ -19,7 +21,7 @@
@Slf4j
public class MenuView {

static String LOGOUT_PAGE = "/logout?faces-redirect=true";
// static String LOGOUT_PAGE = "/logout?faces-redirect=true";

/**
* Kills the sessions. The frontend session will be invalidated during rendering
Expand All @@ -30,7 +32,7 @@ public class MenuView {
*/
public String logout() {
log.info(" #### User logged out. ####");
return LOGOUT_PAGE;
return "/"+LOGOUT_PAGE.getNavigationableAddress()+"?faces-redirect=true";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 by Stefan Schubert under the MIT License (MIT).
* See project LICENSE file for the detailed terms and conditions.
*/

package de.bluewhale.sabi.webclient.controller;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* Nice try (to solve sabi-113) but It won't work for <b>jakarta.faces.application.ViewExpiredException</b>
* as the Controller will be involved in the Context of the DispatcherServlet, which won't happen for errors
* occurring in the JSF engine. The error which has been seen by sabi-113 us happening
* in the Context of the FacesServlet which gets uncaught all way up through the springframework.security.eb Filterchain.
* <p>
* So though this Error-Controller configuration is more or less dead code because of the
* Faces Techstack here, I will leave it with this explanation as reference in it.
*/
@Controller
@Slf4j
public class MyErrorController implements ErrorController {

@RequestMapping("/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

if (status != null) {
Integer statusCode = Integer.valueOf(status.toString());

if (statusCode == HttpStatus.NOT_FOUND.value()) {
return "/static/error/404.html";
} else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return "/static/error/500.html";
}
}

return "/static/error/error.html"; // fallback
}
}
Loading
Loading