Changing the samesite session cookie attribute in a spring webflux application - spring-boot

I am trying to change the same site attribute of my springboot application using WebSessionIdResolver as described here : https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-webflux-custom-cookie.html
#Configuration
public class CookieConfiguration {
#Bean
public WebSessionIdResolver webSessionIdResolver() {
CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
resolver.addCookieInitializer(builder -> builder.sameSite("None"));
return resolver;
}
}
I don't understand what is going, when debugging I can see the bean being initialized,but on every http call a session cookie is written with the default sameSite attribute "Lax", and the default CookieWebSessionIdResolver.cookieInitializer being null.

I was able to solve this adding 'spring-session-core' dependency and using the following config :
#EnableSpringWebSession
#Configuration
public class CookieConfiguration {
#Bean
public WebSessionIdResolver webSessionIdResolver() {
CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
resolver.addCookieInitializer(builder -> builder.sameSite("None"));
return resolver;
}
#Bean
public ReactiveMapSessionRepository reactiveSessionRepository() {
return new ReactiveMapSessionRepository(new ConcurrentHashMap<>());
}
}

Related

Spring session jdbc - How to add multiple HttpSessionIdResolver for a single application

I have a problem in injecting multiple HttpSessionIdResolver for a single spring application.
For normal web application I would like to use CookieHttpSessionIdResolver
For Rest API I would go for HeaderHttpSessionIdResolver and Rest API url will be like "/api/**"
Internally spring sets a bean and uses that bean for all request(In this case HeaderHttpSessionIdResolver
and my web stopped working because i dont set X-Auth-Token header for every request) but i would like to override it.
Could any one please help me.
Thank you.
#EnableJdbcHttpSession(maxInactiveIntervalInSeconds = 3600)
public class SessionConfig extends AbstractHttpSessionApplicationInitializer{
#Autowired
#Qualifier("userDatabase")
private DataSource dataSource;
#Bean
public DataSource dataSource() {
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
#Bean(value = "httpSessionIdResolver")
public HttpSessionIdResolver httpSessionIdResolver() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
#Bean(value = "cookieHttpSessionIdResolver")
public HttpSessionIdResolver cookieHttpSessionIdResolver() {
return new CookieHttpSessionIdResolver();
}
}
I overridden spring session to enable both cookie and header based session.
Now it's working fine.
Currently I'm checking for URL that contains /api/* and if it contains i'm using header based other wise cookie based session.

How to set max-swallow-size in spring boot 2?

I'm trying to set max-swallow-size property of tomcat to -1 in springboot microservice while upgrading to springboot version 2; my earlier code was working but in upgrade some classes have changed so it stopped working.
I tried to set property in two ways but both are not working;
with service configuration
#Bean
public ServletWebServerFactory servletContainerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
#Override
public void customize(Connector connector) {
if(connector.getProtocolHandler() instanceof AbstractHttp11Protocol) {
logger.debug("Setting maxSwallowSize for server connector as "+maxSwallowSize);
((AbstractHttp11Protocol <?>) connector.getProtocolHandler()).setMaxSwallowSize(maxSwallowSize);
}
}
});
return factory;
}
In control flow, I can see the debug line printed but it have not taken effect as end -point response is 502(Bad gateway) instead of 400
Second way :
2. through application.properties file with property
server.tomcat.max-swallow-size=-1
This is also not honored.
Now, How can I verify the property value whether it is actually set or not ?
or Am I setting the value in correct way ?
This New class has resolved my issue
#Component
public class TomcatCustomizer implements
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
#Override
public void customize(TomcatServletWebServerFactory factory) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
#Override
public void customize(Connector connector) {
if(connector.getProtocolHandler() instanceof AbstractHttp11Protocol) {
((AbstractHttp11Protocol <?>) connector.getProtocolHandler()).setMaxSwallowSize(maxSwallowSize);
}
}
});
}
}
and I have used updated properties in spring boot 2.0
spring.servlet.multipart.max-file-size= XX MB
spring.servlet.multipart.max-request-size= YY MB

Problems adding spring webflow to a spring boot and joinfaces application

I am trying to add webflow to a spring boot app using joinfaces library.
I am using primefaces-spring-boot-starter and jetty-spring-boot-starter to configure jetty server.
Added necessary webflow dependencies to pom and configured necessary flowregistry, flowbuilderservices, flowexecutor and flowhandlermapping, ...
The application start correctly, reads the flows definitions from xmls and if enter to a flow via url the decision states are running correctly, reads the corresponding view state .xhtml file, calls the managed bean methods, and all are working apparently well.
But... once finished executing bean methods, when I hope to html be rendered in browser, the application is redirected to app root folder without any error in the log.
I have this behavior with all the flows of the application. Bean methods are executed correctly and when I hope to see the html... redirected to root.
Anyone tried to add webflow to a joinfaces jsf application successfully? I am missing to override some default configuration of joinfaces?
Thanks.
public class MvcConfiguration implements WebMvcConfigurer {
#Autowired
private WebFlowConfiguration webFlowConfiguration;
#Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping handlerMapping = new FlowHandlerMapping();
handlerMapping.setOrder(-1);
handlerMapping.setFlowRegistry(this.webFlowConfiguration.flowRegistry());
return handlerMapping;
}
#Bean
public FlowHandlerAdapter flowHandlerAdapter() {
JsfFlowHandlerAdapter adapter = new JsfFlowHandlerAdapter();
adapter.setFlowExecutor(this.webFlowConfiguration.flowExecutor());
return adapter;
}
#Bean
public ViewResolver faceletsViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setViewClass(JsfView.class);
resolver.setPrefix("/");
resolver.setSuffix(".xhtml");
return resolver;
}
}
#Configuration
public class WebFlowConfiguration extends AbstractFacesFlowConfiguration {
#Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setBasePath("classpath*:/META-INF/resources/flows")
.addFlowLocationPattern("/**/*.xml")
.setFlowBuilderServices(flowBuilderServices())
.build();
}
#Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setDevelopmentMode(true)
.setViewFactoryCreator(new JsfViewFactoryCreator())
.build();
}
#Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.addFlowExecutionListener(new FlowFacesContextLifecycleListener())
.addFlowExecutionListener(new SecurityFlowExecutionListener())
.setMaxFlowExecutionSnapshots(0)
.build();
}
}

Configured ObjectMapper not used in spring-boot-webflux

I have mixins configured in my objectmapperbuilder config, using the regular spring web controller, the data outputted according to the mixins.
However using webflux, a controller with a method returning a Flow or Mono have the data serialized like if the objectmapper a default one.
How to get webflux to enforce an objectmapper configuration to be used ?
sample config:
#Bean
JavaTimeModule javatimeModule(){
return new JavaTimeModule();
}
#Bean
Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.featuresToEnable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.mixIn(MyClass.class, MyClassMixin.class);
}
I actually found my solution by stepping through the init code:
#Configuration
public class Config {
#Bean
JavaTimeModule javatimeModule(){
return new JavaTimeModule();
}
#Bean
Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.featuresToEnable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.mixIn(MyClass.class, MyClassMixin.class);
}
#Bean
Jackson2JsonEncoder jackson2JsonEncoder(ObjectMapper mapper){
return new Jackson2JsonEncoder(mapper);
}
#Bean
Jackson2JsonDecoder jackson2JsonDecoder(ObjectMapper mapper){
return new Jackson2JsonDecoder(mapper);
}
#Bean
WebFluxConfigurer webFluxConfigurer(Jackson2JsonEncoder encoder, Jackson2JsonDecoder decoder){
return new WebFluxConfigurer() {
#Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().jackson2JsonEncoder(encoder);
configurer.defaultCodecs().jackson2JsonDecoder(decoder);
}
};
}
}
I translated the solution of #Alberto Galiana to Java and injected the configured Objectmapper for convenience, so you avoid having to do multiple configurations:
#Configuration
#RequiredArgsConstructor
public class WebFluxConfig implements WebFluxConfigurer {
private final ObjectMapper objectMapper;
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().jackson2JsonEncoder(
new Jackson2JsonEncoder(objectMapper)
);
configurer.defaultCodecs().jackson2JsonDecoder(
new Jackson2JsonDecoder(objectMapper)
);
}
}
Just implement WebFluxConfigurer and override method configureHttpMessageCodecs
Sample code for Spring Boot 2 + Kotlin
#Configuration
#EnableWebFlux
class WebConfiguration : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
configurer.defaultCodecs().jackson2JsonEncoder(Jackson2JsonEncoder(ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)))
configurer.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(ObjectMapper()
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)))
}
}
Make sure all your data classes to be encoded/decoded have all its properties annotated with #JsonProperty even if property name is equal in class and json data
data class MyClass(
#NotNull
#JsonProperty("id")
val id: String,
#NotNull
#JsonProperty("my_name")
val name: String)
In my case, I was trying to use a customized ObjectMapper while inheriting all of the behavior from my app's default WebClient.
I found that I had to use WebClient.Builder.codecs. When I used WebClient.Builder.exchangeStrategies, the provided overrides were ignored. Not sure if this behavior is something specific to using WebClient.mutate, but this is the only solution I found that worked.
WebClient customizedWebClient = webClient.mutate()
.codecs(clientCodecConfigurer ->
clientCodecConfigurer.defaultCodecs()
.jackson2JsonDecoder(new Jackson2JsonDecoder(customObjectMapper)))
.build();
I have tried all the different solutions (#Primary #Bean for ObjectMapper, configureHttpMessageCodecs(), etc.). What worked for me at the end was specifying a MIME type. Here's an example:
#Configuration
class WebConfig: WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
val encoder = Jackson2JsonEncoder(objectMapper, MimeTypeUtils.APPLICATION_JSON)
val decoder = Jackson2JsonDecoder(objectMapper, MimeTypeUtils.APPLICATION_JSON)
configurer.defaultCodecs().jackson2JsonEncoder(encoder)
configurer.defaultCodecs().jackson2JsonDecoder(decoder)
}
}

Spring injects null instead of a class instance

Here's a piece of Spring config file:
#Bean
public GenericDao<Foo> fooDao() {
return new GenericDao<>(Foo.class);
}
#Bean
#DependsOn("fooDao")
public GenericService<Foo> fooService() {
return new ApplicationGenericService<>(fooDao(), applicationMessageProducer());
}
#Bean
#DependsOn("fooService")
public GenericService<Foo> decoratedFooService() {
return new ServiceDecorator<>(fooService(), decoratorService());
}
For some reason, Spring passes null to ApplicationGenericService constructor.
Any ideas how to fix this issue?

Resources