Search code examples
javaspring-mvcsecurityservletshdiv

HDIV + Spring MVC - getting always Unauthorized Access error HDIV_PARAMETER_DOES_NOT_EXIST


I am using HDIV with Spring MVC based on Spring Java Configuration which I derived from their showcase implementation. The configuration get loaded but when I try to access protected URLs i.e. "/messages/message" I get always Unauthorized Access error HDIV_PARAMETER_DOES_NOT_EXIST. It works when I change the config to exclude the URL from HDIV processing but this of course is not an option

Anybody an idea what I missed?

Logfile error statement

10:04:17.304 [http-nio-8080-exec-22] INFO  org.hdiv.logs.Logger - HDIV_PARAMETER_DOES_NOT_EXIST;/spring-security-example/messages/message;_HDIV_STATE_;;;127.0.0.1;127.0.0.1;megloff;

Java Configuration

@Configuration
@EnableHdivWebSecurity
public class HdivSecurityConfig extends HdivWebSecurityConfigurerAdapter {

  @Override
  public void configure(SecurityConfigBuilder builder) {
  }

  @Override
  public void addExclusions(ExclusionRegistry registry) {
    registry.addUrlExclusions("/").method("GET");
    registry.addUrlExclusions("/login");
    registry.addUrlExclusions("/logout");
    registry.addUrlExclusions("/static/.*");
    registry.addParamExclusions("_csrf");  


    //  registry.addUrlExclusions("/messages/.*"); <-- would allow access, but not an option      
  }

  @Override
  public void configureEditableValidation(ValidationConfigurer validationConfigurer) {

    validationConfigurer.addValidation("/messages/.*");
    validationConfigurer.addValidation("/addUser");
  }
}

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {
    "ch.megloff.spring.security.example.mvc.controller",
    "ch.megloff.spring.security.example.mvc.action",
    "ch.megloff.spring.security.example.repository",
    "ch.megloff.spring.security.example.listener", 
    "ch.megloff.spring.security.example.service"})
public class SpringMVCConfiguration extends WebMvcConfigurerAdapter {

  @Autowired
  @Qualifier("hdivEditableValidator")
  private Validator hdivEditableValidator;

  @Override
  public Validator getValidator() {
    return hdivEditableValidator;
 }

 ...
}


public class SpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
    return new Class[] { SpringMVCConfiguration.class, SpringHibernateConfig.class, SpringSecurityConfiguration.class, SpringSecurityJDBCConfiguration.class, SpringWebFlowConfig.class, HdivSecurityConfig.class };
}

   @Override
   protected Class<?>[] getServletConfigClasses() {
    return new Class[] { SpringMVCConfiguration.class };
   }

   @Override
   protected String[] getServletMappings() {
    return new String[] { "/" };
   }

   public void onStartup(ServletContext container) throws ServletException {
    super.onStartup(container);

    container.addFilter("ValidatorFilter", ValidatorFilter.class).addMappingForUrlPatterns(
            EnumSet.of(DispatcherType.REQUEST), false, "/*");

    container.addListener(new InitListener());
  }
}

Solution

  • I found a solution. HDIV requires that all links get enriched with a "_HDIV_STATE_" parameter in its URL. in order to achieve that you have to use taglib from HDIV and not the original JSTL taglib.

    Please refer also to the reference documentation of HDIV regarding JSTL

    e.g. in your POM

        <dependency>
            <groupId>org.hdiv</groupId>
            <artifactId>hdiv-jstl-taglibs-1.2</artifactId>
            <version>${org.hdiv-version}</version>
        </dependency>
    

    e.g. in your JSP (note the 'www.hdiv.org' in the taglib statement)

    <%@ taglib prefix="c" uri="http://www.hdiv.org/jsp/jstl/core"%> <c:url value="/messages/messages" var="url" /> <li><a href="${url}">Messages</a></li>

    So you need to render the URL via th <c:url> utility tag. This renders then the URL with the required HDIV parameter i.e.

    localhost:8080/spring-security-example/messages/message?_HDIV_STATE_=26-0-830046F08D66980D1B35F52F2D6677E0
    

    another option may be is to use the utility class from HDIV see class LinkUrlProcessor at the github repository of hdiv

    LinkUrlProcessor urlProcessor = HDIVUtil.getLinkUrlProcessor(servletContext);
    String processUrl = urlProcessor.processUrl(request, "/messages/messages");