Skip to content

Provide a way to configure channel processor's retry redirect strategies  #7997

@okohub

Description

@okohub

Hello good people,

Https is broadly used in nowadays and most of sites redirecting their http urls to https. But it is somewhat better to do with "SC_MOVED_PERMANENTLY (301)" status, rather than response.sendRedirect which is 302.

Modifying this a bit painful.

org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer#getChannelProcessors

This method actually gives an opportunity to use provided processors. But I think we can add more customisable areas to use power of this method directly.

Let me give an example for our current solution. PermanentRedirectStrategy class is our redirection strategy to make permanent redirection. A simple class which is:

public class PermanentRedirectStrategy extends DefaultRedirectStrategy {

  @Override
  public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException {
    String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
    redirectUrl = response.encodeRedirectURL(redirectUrl);
    if (logger.isDebugEnabled()) {
      logger.debug("Redirecting to '" + redirectUrl + "'");
    }
    response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
    response.setHeader("Location", redirectUrl);
    response.flushBuffer();
  }
} 

Using this strategy is not easy. We needed to copy whole method and set this strategy to each processor.

/**
   * @see ChannelSecurityConfigurer#getChannelProcessors(HttpSecurityBuilder)
   */
  private static List<ChannelProcessor> getCustomizedChannelProcessors(PortMapper portMapper) {
    InsecureChannelProcessor insecureChannelProcessor = new InsecureChannelProcessor();
    SecureChannelProcessor secureChannelProcessor = new SecureChannelProcessor();
    //
    RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint();
    httpEntryPoint.setPortMapper(portMapper);
    httpEntryPoint.setRedirectStrategy(new PermanentRedirectStrategy());
    insecureChannelProcessor.setEntryPoint(httpEntryPoint);
    //
    RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint();
    httpsEntryPoint.setPortMapper(portMapper);
    httpsEntryPoint.setRedirectStrategy(new PermanentRedirectStrategy());
    secureChannelProcessor.setEntryPoint(httpsEntryPoint);
    //
    return List.of(insecureChannelProcessor, secureChannelProcessor);
  }

Then apply to core config:

ChannelSecurityConfigurer configurer = http.getConfigurer(ChannelSecurityConfigurer.class);
    PortMapper portMapper = http.getSharedObject(PortMapper.class);
    if (Objects.isNull(portMapper)) {
      portMapper = new PortMapperImpl();
    }
    List<ChannelProcessor> customizedChannelProcessors = getCustomizedChannelProcessors(portMapper);
    configurer.getRegistry().channelProcessors(customizedChannelProcessors);

You see? So I thought, we can provide some injection points to set insecureChannelProcessor's redirect strategy as well as secureChannelProcessor's redirect strategy.

Or, another solution if you can suggest of course :)

What do you think?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions