jeffwils / grails-spring-security-saml

Grails Spring Security SAML2.0 Plugin for Grails 3
8 stars 25 forks source link

Encoding problem #63

Closed bhdzllr closed 4 years ago

bhdzllr commented 4 years ago

Hello,

We use "grails-spring-security-saml" in one of our application and with Grails 4.0.0. After adding the plugin the encoding of forms doesn't work anymore.

It's a regular form with a textarea and encoding for characters like "ö" is not working, e. g. "ö" become "ö".

Removing these two filters make it work: -httpPutFormContentFilter,-filterInvocationInterceptor.

Is there anything I can do or maybe I'm doing something wrong? Thank you.

grails.plugin.springsecurity.filterChain.chainMap = [
    [pattern: '/assets/**',      filters: 'none'],
    [pattern: '/**/js/**',       filters: 'none'],
    [pattern: '/**/css/**',      filters: 'none'],
    [pattern: '/**/images/**',   filters: 'none'],
    [pattern: '/**/favicon.ico', filters: 'none'],
    [pattern: '/**',             filters: 'JOINED_FILTERS,-httpPutFormContentFilter,-filterInvocationInterceptor']
valentingoebel commented 4 years ago

I have looked into it and not found any bugs in the plugin itself. I can reproduce the problem simply by copying the dependencies of the plugin into a sample app. So far I am not sure which dependency is causing it.

bhdzllr commented 4 years ago

I think the two filters are from "grails-spring-security-core", but further maybe directly from spring. I don't have any idea for a workaround besides removing the two filters.

valentingoebel commented 4 years ago

It doesn't look like the problem has to do with those two filters. It's just that they are the only ones that read the request's inputstream while the encoding is set to null.

There has been a change in the spring-security-config plugin in 3.2.0. The first milestone release `compile 'org.springframework.security:spring-security-config:3.2.0.M1' still works but 3.2.0.RELEASE and beyond don't.

I have modified the GrailsHttpPutFormContentFilter to abort and throw an Exception. The filter chain is visible in the stacktrace.

Here is the diff of the stacktrace between 3.2.0.M1 and 3.2.0.RELEASE.

-java.lang.RuntimeException: Encoding: UTF-8
+java.lang.RuntimeException: Encoding: null
         at grails.plugin.springsecurity.web.filter.GrailsHttpPutFormContentFilter.doFilterInternal(GrailsHttpPutFormContentFilter.groovy:40)
         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
         at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
@@ -32,18 +32,8 @@ java.lang.RuntimeException: Encoding: UTF-8
         at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
         at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
         at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
-        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
-        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
-        at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
-        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
-        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
-        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
-        at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
-        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
-        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
-        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
-        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
-        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
+        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
+        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
         at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)

The problem isn't that we have one or two filters too many. We are actually missing a quite large amount of important filters like the CharacterEncodingFilter, which properly sets the encoding.

Something like this shouldn't happen from a mere minor version bump. I still have no clue what causes the problem.

valentingoebel commented 4 years ago

The latest version of spring-security-core triggers the loading of SecurityFilterAutoConfiguration which I thought has been removed in spring boot 2.

The workaround is still the same as mentioned in this issue except with a new path:

https://github.com/jeffwils/grails-spring-security-saml/issues/3

In your Application.groovy add the following lines.

package app

import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration

@EnableAutoConfiguration(exclude = [SecurityFilterAutoConfiguration])
class Application extends GrailsAutoConfiguration {
    static void main(String[] args) {
        GrailsApp.run(Application, args)
    }
}

I do not know why newer versions of spring-security-core trigger SecurityFilterAutoConfiguration in spring boot 2 but since this workaround was needed in the old 3.3.0 version anyway it means we can keep version 4.0.0 as is for the time being until a permanent solution has been found.

valentingoebel commented 4 years ago

Overriding the beans springSecurityFilterChain and securityFilterChainRegistration in https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/SecurityFilterAutoConfiguration.java seems to be enough to prevent Spring Boot from installing it's own filter chain and lets grails configure it's own.

Fixed by https://github.com/jeffwils/grails-spring-security-saml/commit/ba4ef424e271ef6b0a0920dcdaee810f7ce220c7

bhdzllr commented 4 years ago

Thank you very much Valentin, the workaround works for me, will use it until a new release.