当前位置: 首页 > 面试题库 >

码头-如何以编程方式在web.xml中强制实施安全约束

万俟高峻
2023-03-14
问题内容

在我们的web.xml中,我们具有以下安全约束

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Everything on the app</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

这很有效,除了我们需要以编程方式打开和关闭此约束之外,因此本质上需要编写一个过滤器来执行类似的操作。这可以在码头做吗?从本质上讲,我们需要能够基于自定义配置系统更改此功能的打开或关闭。


问题答案:

可以在Jetty中进行操作,但我认为您不能在jetty.xml中有条件地进行操作。

我知道您可以通过在应用程序中嵌入Jetty并以编程方式配置和实例化您的Jetty服务器来做到这一点。我不知道这如何适合您的部署方案,但是这里有一个嵌入式Jetty服务器的示例,该服务器在所有连接上都强制使用机密信息。您可以对其进行修改,以有条件地应用ConstraintSecurityHandler(内置于buildConstraintSecurityHandler的调用中),具体取决于您的自定义配置的设置方式。

package com.example.webapp;

import com.example.webapp.guice.ProdModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.commons.codec.binary.Base64;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.glassfish.jersey.servlet.ServletContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Collections;
import java.util.Properties;

public class EmbeddedServer {
    static Server server = null;
    private final static String componentUUID = "f2dsfb1d-9e7a-4c9f-984e-ee5sdfa68d60";
    private static String getHandlerPackages() {
        return "com.example";
    }
    private static Properties properties;
    final static Logger log = LoggerFactory.getLogger(EmbeddedServer.class);

    static PrivateKey createPrivateKey(String keyFileName) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

        // see https://www.openssl.org/docs/HOWTO/certificates.txt
        PrivateKey privateKey;

        FileInputStream fis = new FileInputStream(keyFileName);
        InputStreamReader isr = new InputStreamReader(fis);
        BufferedReader br = new BufferedReader(isr);

        // TODO Handle DER format private keys

        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

        String pemString = sb.toString();

        pemString = pemString.replace("-----BEGIN PRIVATE KEY-----", "");
        pemString = pemString.replace("-----END PRIVATE KEY-----", "");


        Base64 decoder = new Base64();

        byte[] encoded = decoder.decode(pemString);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        privateKey = kf.generatePrivate(keySpec);

        return privateKey;
    }

    private static KeyStore createJavaKeyStore(String certFileName, String keyFileName) throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, InvalidKeySpecException {
        // see https://www.openssl.org/docs/HOWTO/keys.txt
        KeyStore ks = KeyStore.getInstance("JKS");
        FileInputStream fis = new FileInputStream(certFileName);
        BufferedInputStream bis = new BufferedInputStream(fis);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate cert = null;

        // load the x.509 certificate
        while (bis.available() > 0) {
            cert = cf.generateCertificate(bis);
        }

        bis.close();
        fis.close();

        ks.load(null, null);

        ks.setKeyEntry("keyentry,", createPrivateKey(keyFileName), componentUUID.toCharArray(), new Certificate[]{cert});

        return ks;
    }


    public static Server createServerWithConnectors() throws IOException, InvalidKeySpecException, CertificateException, NoSuchAlgorithmException, KeyStoreException {
        Server server = new Server();
        SslContextFactory sslContextFactory;

        KeyStore ks = createJavaKeyStore("ssl/cacertpemkey.pem", "ssl/privkey.pem");

        sslContextFactory = new SslContextFactory();
        sslContextFactory.setKeyStore(ks);
        sslContextFactory.setKeyStorePassword(componentUUID);

        // HTTP Configuration
        // HttpConfiguration is a collection of configuration information appropriate for http and https. The default
        // scheme for http is <code>http</code> of course, as the default for secured http is <code>https</code> but
        // we show setting the scheme to show it can be done.  The port for secured communication is also set here.
        HttpConfiguration http_config = new HttpConfiguration();
        http_config.setSecureScheme("https");
        http_config.setSecurePort(getPort(true));
        http_config.setOutputBufferSize(32768);

        // HTTP connector
        // The first server connector we create is the one for http, passing in the http configuration we configured
        // above so it can get things like the output buffer size, etc. We also set the port (8080) and configure an
        // idle timeout.
        ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config));
        http.setPort(getPort(false));
        http.setIdleTimeout(30000);

        // HTTPS Configuration
        // A new HttpConfiguration object is needed for the next connector and you can pass the old one as an
        // argument to effectively clone the contents. On this HttpConfiguration object we add a
        // SecureRequestCustomizer which is how a new connector is able to resolve the https connection before
        // handing control over to the Jetty Server.
        HttpConfiguration https_config = new HttpConfiguration(http_config);
        https_config.addCustomizer(new SecureRequestCustomizer());

        // HTTPS connector
        // We create a second ServerConnector, passing in the http configuration we just made along with the
        // previously created ssl context factory. Next we set the port and a longer idle timeout.
        ServerConnector https = new ServerConnector(server,
                new SslConnectionFactory(sslContextFactory, "http/1.1"),
                new HttpConnectionFactory(https_config));
        https.setPort(getPort(true));
        https.setIdleTimeout(500000);

        // Here you see the server having multiple connectors registered with it, now requests can flow into the server
        // from both http and https urls to their respective ports and be processed accordingly by jetty. A simple
        // handler is also registered with the server so the example has something to pass requests off to.

        // Set the connectors
        server.setConnectors(new Connector[]{http, https});

        return server;
    }

    public static int getPort(boolean secure)  {
        String s;
        if (secure)
            s = properties.getProperty("secure.port", "8443");
        else
            s = properties.getProperty("port", "8080");

        return Integer.parseInt(s);
    }

    public static void stopServer()
    {
        if (server != null)  {
            try {
                server.stop();
            } catch (Exception e) {
                log.info("Exception in stopServer", e);
            }
        }
    }

    public static Server startServerIfNeeded()
    {
        if (server == null) {
            try {
                server = createServerWithConnectors();
                HandlerList handlers = buildServerHandlers();
                server.setHandler(handlers);
                server.start();
                server.join();
            } catch (Exception e) {
                log.info("Exception in startServerIfNeeded", e);
            }
        }

        return server;
    }


    public static void main(String [] args)
    {
        log.info("Embedded server startup");
        properties = Util.getProperties("embeddedserver.properties");
        startServerIfNeeded();
    }

    private static HandlerList buildServerHandlers() {
        HandlerList handlers = new HandlerList();

        ConstraintSecurityHandler securityHandler = buildConstraintSecurityHandler();
        ServletContextHandler servletContexttHandler = buildJerseyServletHandler();
        securityHandler.setHandler(servletContexttHandler);
        handlers.addHandler(securityHandler);

        securityHandler = buildConstraintSecurityHandler();
        ContextHandler ch  = buildStaticResourceHandler();
        securityHandler.setHandler(ch);
        handlers.addHandler(securityHandler);

        return handlers;
    }

    private static ServletContextHandler buildJerseyServletHandler() {
        ServletContextHandler servletContextHandler = new ServletContextHandler(
                ServletContextHandler.SESSIONS);

        servletContextHandler.setContextPath("/api");
        servletContextHandler.setErrorHandler(new MyServletContextErrorHandler());
        servletContextHandler.addEventListener(new MyServletContextListener());
        servletContextHandler.setAttribute(Injector.class.getName(), Guice.createInjector(new ProdModule()));
        servletContextHandler.addFilter(new FilterHolder(new LoggingFilter()),"/*",null);

        ServletHolder servletHolder = new ServletHolder(new ServletContainer());

        String packageList = getHandlerPackages();
        servletHolder.setInitParameter(
                "jersey.config.server.provider.packages", packageList);
        servletContextHandler.addServlet(servletHolder, "/*");

        return servletContextHandler;
    }

    private static ContextHandler buildStaticResourceHandler() {
        // if you want the static content to serve off a url like
        // localhost:8080/files/.... then put 'files' in the constructor
        // to the ContextHandler
        ContextHandler ch = new ContextHandler("/");
        ResourceHandler rh = new ResourceHandler();
        rh.setWelcomeFiles(new String[]{"index.html"});
        rh.setResourceBase(properties.getProperty("static.resource.base"));
        ch.setHandler(rh);
        return ch;
    }

    private static ConstraintSecurityHandler buildConstraintSecurityHandler() {
        // this configures jetty to require HTTPS for all requests
        Constraint constraint = new Constraint();
        constraint.setDataConstraint(Constraint.DC_CONFIDENTIAL);
        ConstraintMapping mapping = new ConstraintMapping();
        mapping.setPathSpec("/*");
        mapping.setConstraint(constraint);
        ConstraintSecurityHandler security = new ConstraintSecurityHandler();
        security.setConstraintMappings(Collections.singletonList(mapping));
        return security;
    }
}


 类似资料:
  • 我已经知道如何配置Tomcat,以便它将HTTP请求重定向到HTTPS: 启用并配置SSL连接器 在非SSL连接器上设置正确的“重定向端口”属性 修改web.xml并将传输保证设置为机密 我的问题是:有没有一种方法可以在不修改web.xml文件的情况下实现相同的结果? 我正在寻找一种不必更改Web应用程序的解决方案,它被部署为WAR文件。因此,添加servlet过滤器或在Web应用程序中实现重定向

  • 我在通用应用程序的底部显示一个视图,并在视图中动态添加该视图。我希望每次都能像iAd一样在底部显示这个视图。在两个方向上。如何为此添加约束。请建议。 谢谢

  • 我已经为我的视图控制器使用了自动布局。我已经在约束中设置了V和H位置,但是我想知道当它变为5s,6和6 Plus时如何增加我的按钮大小。这是我为登录按钮添加约束的方式: 但我的问题是,当它管理左右两侧间隙时,由于高度是固定的,它在iPhone6和6 Plus中被拉伸。我如何根据屏幕尺寸增加尺寸?我想这可能是长宽比,但我如何在代码中设置长宽比约束?

  • 问题内容: 如何以编程方式在输入上强制发生onchange事件? 我已经尝试过这样的事情: 但是我的最终目标是触发任何侦听器功能,但这似乎不起作用。只是更新’value’属性也不会。 问题答案: 创建一个对象并将其传递给元素的方法: 这将触发事件侦听器,无论它们是通过调用方法还是通过设置元素的属性进行注册的。 如果您希望事件冒泡,则需要将第二个参数传递给构造函数:

  • 问题内容: 我正在用python,selenium和firefox运行此代码,但仍获得firefox的“ head”版本: 我还尝试了一些二进制的变体: 问题答案: 要不费吹灰之力地调用Firefox浏览器,可以通过以下类设置属性: 还有另一种方法可以完成无头模式。如果你需要禁用或启用Firefox中的无头模式,而无需修改代码,您可以设置环境变量,以 什么 ,如果你想Firefox的运行无头,或根

  • 当仅仅声明式安全是不足以表达应用的安全模型时,编程式安全被用于意识到安全的应用。 编程式安全包括以下 HttpServletRequest 接口的方法: authenticate login logout getRemoteUser isUserInRole getUserPrincipal login 方法允许应用执行用户名和密码收集(作为一种 Form-Based Login 的替代)。 au