• spring-boot-starter-parent:2.4.0
  • I have @Controller with path function with parm @RequestHeader Map<String, String> allHeaders
  • Post request with some custom http header key sn: Tomažč but I got error
  • error:
[org.springframework.security.web.firewall.StrictHttpFirewall$StrictFirewalledRequest.validateAllowedHeaderValue(StrictHttpFirewall.java:739),
 org.springframework.security.web.firewall.StrictHttpFirewall$StrictFirewalledRequest.getHeader(StrictHttpFirewall.java:628),
 javax.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88),
 javax.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88),
 org.springframework.web.context.request.ServletWebRequest.getHeader(ServletWebRequest.java:129),
 org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver.resolveArgument(RequestHeaderMapMethodArgumentResolver.java:83),
 org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121),
 org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170),
 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137),
 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106),
 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893),
 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:807),
 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87),
 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061),
 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961),
 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006),
 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898),
 javax.servlet.http.HttpServlet.service(HttpServlet.java:626),
 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883),
 javax.servlet.http.HttpServlet.service(HttpServlet.java:733),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327),
 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115),
 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119),
 org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126),
 org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 si.arnes.dmsedu.security.JwtAuthorizationTokenFilter.doFilterInternal(JwtAuthorizationTokenFilter.java:41),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103),
 org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90),
 org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110),
 org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119),
 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336),
 org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211),
 org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183),
 org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358),
 org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201),
 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119),
 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193),
 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166),
 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202),
 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97),
 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542),
 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143),
 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92),
 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78),
 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343),
 org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374),
 org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65),
 org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868),
 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590),
 org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49),
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149),
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624),
 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61),
 java.lang.Thread.run(Thread.java:748)]

Comment From: bclozel

HTTP headers usually only allow ASCII characters or strings encoded with MIME header encoding. Is that the case in your sample application?

If the header is properly encoded, could you please provide a sample project reproducing the issue (ideally something simple we can git clone and run to reproduce the problem)?

Thanks!

Comment From: sysmat

  • ok but why is char ž ok, is also non-ASCII and there is no error
  • with spring-boot-starter-parent:2.3.6.RELEASE works like a charm, no problems with non-ASCII header values

Comment From: wilkinsona

@sysmat A sample project will help us to figure that out.

Comment From: sysmat

It's is from https://start.spring.io/ * maven

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>si.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • main
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
  • controller
@RestController
public class RestApi {

    @GetMapping("/headers")
    public String headers(@RequestHeader Map<String, String> allHeaders) {
        allHeaders.forEach((key, value) -> System.out.println("key="+key+", value="+value));
        return "oj";
    }

}
  • ResourcesExceptionHandler:
@ControllerAdvice
@RestController
public class ResourcesExceptionHandler {    

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = Exception.class)
    public void generalException(Exception e) {
        System.out.error("Exception="+ e.getMessage()+ "casue="+e.getCause()+"stack="+e.getStackTrace());        
    }
}
  • client

curl http://localhost:8080/headers -H "name: tomažč"

Comment From: snicoll

@sysmat thank you but if you have the project at hand, please share it so that we don't have to copy paste all that text in something that we can run.

Comment From: wilkinsona

This is standard behaviour in Spring Security 5.4 to which Spring Boot 2.4 upgraded. This is mentioned in the Spring Security documentation which also provides some information about configuring the behaviour

Comment From: sysmat

thanks I did't find in change log

Comment From: sysmat

@snicoll English is not my main language, so my expression is limited * sorry that I can't share the main project and environment, but I can share with you the concept of reading non-ASCII HTTP headers values in this framework is in a big problem.
* is spring semantic versioning compliment * is spring java ee? * is spring rfc compliment * is spring developer-friendly

The main point of issues is not that your users solve your problem but you listen to the problem

Comment From: philwebb

Sorry that I can't share the main project and environment, but I can share with you the concept of reading non-ASCII HTTP headers values in this framework is in a big problem.

Apologies for the confusion, we weren't asking for you to share your main project, we just find it easier when there's a small sample project in a git repo that we can download and run. As you can imagine, we have a lot of issues to deal with so it's always helpful if we can save time when reproducing a bug.

is spring semantic versioning compliment

No it isn't. We don't follow semantic versioning.

is spring java ee?

No

is spring rfc compliment

Depends on the RFC

is spring developer-friendly

I'd like to think so

The main point of issues is not that your users solve your problem but you listen to the problem

Not all users have the same problem. See https://github.com/spring-projects/spring-security/pull/8644 for background about why this change was made.