通过端口/连接器暴露/过滤控制器请求映射



我有一个相对简单的Spring Boot应用程序,默认情况下,使用自签名证书在端口9443上通过SSL进行保护,这对于为移动应用程序提供api非常有效。但是,我现在想开发一个具有自己前端的不安全web应用程序,并提供我允许的内容的子集SSL。

这是我到目前为止所想到的,除了在application.properties中定义的端口9443之外,它还在HTTP上启用了端口8080:

@SpringBootApplication
@ComponentScan
public class Application extends WebMvcConfigurerAdapter {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        tomcat.addAdditionalTomcatConnectors(createWebsiteConnector());
        return tomcat;
    }
    private Connector createWebsiteConnector() {
        Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
        connector.setPort(8080);
        return connector;
    }
}

我现在面临的任务是只将端点暴露给8080连接,并将所有端点暴露给9443。显然,后者目前默认工作,但现在8080可以访问9443可以访问的所有内容。理想情况下,我希望控制对两个连接都可以访问的"共享"控制器中定义的某些请求映射的访问,例如:

@RequestMapping(value = "/public", method = RequestMethod.GET)
public List<String> getPublicInfo() {
    // ...
}
@HTTPSOnly
@RequestMapping(value = "/secured", method = RequestMethod.GET)
public List<String> getSecuredInfo() {
    // ...
}

我假设我上面的东西实际上是不可能的,但是有人知道我如何才能达到同样的效果吗?

提前感谢您的帮助!

好吧,我想我实际上自己解决了这个问题,但如果有人认为他们有更好的解决方案,我愿意接受其他建议:

@SpringBootApplication
@ComponentScan
public class Application extends WebMvcConfigurerAdapter {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        tomcat.addAdditionalTomcatConnectors(createWebsiteConnector());
        return tomcat;
    }
    private Connector createWebsiteConnector() {
        Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
        connector.setPort(8080);
        return connector;
    }
    private static HashSet<String> uriWhitelist = new HashSet<>(4);
    static {
        // static website content
        uriWhitelist.add("/");
        uriWhitelist.add("/index.html");
        uriWhitelist.add("/logo_48x48.png");
        // public APIs
        uriWhitelist.add("/public");
    }
    private static class PortFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            if (request instanceof RequestFacade) {
                RequestFacade requestFacade = (RequestFacade) request;
                if (requestFacade.getServerPort() != 9443 && !uriWhitelist.contains(requestFacade.getRequestURI())) {
                    // only allow unsecured requests to access whitelisted endpoints
                    return;
                }
            }
            filterChain.doFilter(request, response);
        }
    }
    @Bean
    public FilterRegistrationBean portFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        PortFilter filter = new PortFilter();
        filterRegistrationBean.setFilter(filter);
        return filterRegistrationBean;
    }
}

最新更新