How can I tell spring security to apply authorizeRequests just for a specific port? How can I tell spring security to apply authorizeRequests just for a specific port? spring spring

How can I tell spring security to apply authorizeRequests just for a specific port?


I found a solution:

The authorizeRequests() method here returns an ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry, which has (from its ancestor class AbstractRequestMatcherRegistry) beside some antMatchers methods also a generic requestMatchers() method, which takes one or more RequestMatcher objects. It turns out this is an interface I can implement myself:

/** * A request matcher which matches just a port. * * @param   port  the port to match. * * @return  the new matcher. */private RequestMatcher forPort(final int port) {    return (HttpServletRequest request) -> port == request.getLocalPort();}

(This is Java 8 syntax, with previous Java versions you'll had to write an anyonymous class here.)

While requestMatchers takes several such matchers, it looks like those are connected by OR (at least this example suggests this), thus I used an AndRequestMatcher to connect it to the matcher for the path (and HTTP method)).

The final code looked like this:

@Value("${management.port}")private int managementPort;@Value("${server.port}")private int apiPort;/** * Configure scopes for specific controller/httpmethods/roles here. */@Overridepublic void configure(final HttpSecurity http) throws Exception {    //J-    http        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)        .and()        .authorizeRequests()            .requestMatchers(forPortAndPath(managementPort, "/info")).anonymous()            .requestMatchers(forPortAndPath(managementPort, "/health")).anonymous()            .requestMatchers(forPortAndPath(apiPort, HttpMethod.GET, "/warehouses/**")).access(oauthScopeRead)            .requestMatchers(forPortAndPath(apiPort, HttpMethod.PUT, "/warehouses/**")).access(oauthScopeWrite)            .anyRequest().denyAll();    //J+}/** * Creates a request matcher which only matches requests for a specific local port and path (using an * {@link AntPathRequestMatcher} for the path part). * * @param   port         the port to match * @param   pathPattern  the pattern for the path. * * @return  the new request matcher. */private RequestMatcher forPortAndPath(final int port, @Nonnull final String pathPattern) {    return new AndRequestMatcher(forPort(port), new AntPathRequestMatcher(pathPattern));}/** * Creates a request matcher which only matches requests for a specific local port, path and request method (using * an {@link AntPathRequestMatcher} for the path part). * * @param   port         the port to match * @param   pathPattern  the pattern for the path. * @param   method       the HttpMethod to match. Requests for other methods will not be matched. * * @return  the new request matcher. */private RequestMatcher forPortAndPath(final int port, @Nonnull final HttpMethod method,        @Nonnull final String pathPattern) {    return new AndRequestMatcher(forPort(port), new AntPathRequestMatcher(pathPattern, method.name()));}/** * A request matcher which matches just a port. * * @param   port  the port to match. * * @return  the new matcher. */private RequestMatcher forPort(final int port) {    return (HttpServletRequest request) -> { return port == request.getLocalPort(); };}

This does not fully reflect the question: the managementPort has here just "/info" and "/health" public reachable, instead of everything.

You could use this

                 .requestMatchers(forPort(managementPort)).anonymous()

to make this port fully unauthorized.


A straightforward way to permit all access to management endpoints, regardless of which port they are running on:

http.authorizeRequests()    .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll();

The org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest#toAnyEndpoint method returns a matcher that only matches actuator requests.

See spring-boot-smoke-tests for a more complete example.


Based in the previous answer I develop this class that excludes the admin port from the security. I hope this helps:

@EnableWebSecurity@Configurationpublic class WebSecurityAdapter extends WebSecurityConfigurerAdapter {  /**   * Puerto de administración por donde escucha Actuator.   */  @Value("${management.server.port}")  private int managementPort;  /*   * (non-Javadoc)   *    * @see org.springframework.security.config.annotation.web.configuration.   * WebSecurityConfigurerAdapter#configure(org.springframework.security.config.   * annotation.web.builders.WebSecurity)   */  @Override  public void configure(WebSecurity web) throws Exception {    web.ignoring().requestMatchers(forPort(managementPort));  }  /**   * @param port   *          Puerto que se desea comparar con el puerto de la respuesta http.   * @return Verdadero si el puerto de la respuesta http es igual al puerto   *         especificado.   */  private RequestMatcher forPort(int port) {    return (HttpServletRequest request) -> {      return port == request.getLocalPort();    };  }}