Friday, November 30, 2018

Configure Spring Boot to use HTTPS


If you're writing a Spring Boot application and want to and enable SSL (https) on the embedded Tomcat, here a few short steps you will need to take. (This has been tested with Spring Boot 2.0.5.RELEASE.)
  1. Get an SSL certificate.
    Fortunately, Java has a tool for doing this called keytool.
    keytool -genkey -alias tomcat \
     -storetype PKCS12 -keyalg RSA -keysize 2048 \
     -keystore keystore.p12 -validity 365
    What does each flag mean? Let's break it down.
    • -genkeypair Generates a key pair (a public key and associated private key), wraps the public key into an X.509 v3 self-signed certificate, which is stored as a single-element certificate chain.
    • -alias tomcat This is how we will refer to the key pair in the keystore. Here we are going to call it 'tomcat'.
    • -storetype PKCS12 This is the archive file format, used to bundle the private key with its certificate. Here we are using PKCS 12.
    • -keyalg RSA Specifies the algorithm to be used to generate the key pair. Here we are using RSA .
    • -keysize 2048 The size (in bytes) of each key to be generated. Here we specify 2K.
    • -keystore keystore.p12. The name of the keystore file to generate. Here we are calling it 'keystore.p12'.
    • -validity 365 How long the certificate is valid. Here we specify 1 year.
    Since we did not use the -dname flag, keytool will interactively ask you questions for the certificate's distinguished name: 
    Since this is for development, you may simply press 'Enter' at each prompt. (Be sure to answer 'yes' at the end though.) 
  2. Enable HTTPS in Spring Boot
    This part is pretty simple. Open your Spring Boot application.properties and configure it like this:
    server.port: 8443
    server.ssl.key-store: keystore.p12
    server.ssl.key-store-password: mypassword
    server.ssl.keyStoreType: PKCS12
    server.ssl.keyAlias: tomcat
    Restart your app and test the URL at https://localhost:8443. Since we self-signed our certificate, you will see an ugly warning like this:

    Depending on your browser, navigate to the 'Advanced' option and proceed to your application.
  3. Redirect HTTP to HTTPS
    Wouldn't it be nice if the old port redirected to this new secure port? Yes, it would.
    We will need to add a second Tomcat connector. However, we cannot do it in the application.properties So we'll have to do it programmatically, by creating our own TomcatServletWebServerFactory and overriding the postProcessContext method. 
    Add this code to one of your @Configuration beans (except for WebSecurityConfigurerAdapter, if you're using one):
    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory serverFactory = new TomcatServletWebServerFactory() {
    
            @Override
            protected void postProcessContext(Context context) {
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
    
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL");
                securityConstraint.addCollection(collection);
    
                context.addConstraint(securityConstraint);
            }
        };
    
        serverFactory.addAdditionalTomcatConnectors(redirectConnector());
    
        return serverFactory;
    }
    
    private Connector redirectConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        connector.setRedirectPort(8443);
        return connector;
    }
    
    Restart your app and test the URL at http://localhost:8080. Yay! It redirects to https.

Tuesday, November 27, 2018

Sorting Algorithm Complexity Cheat Sheet


Here is a handy summary table of the time complexity of some popular sorting algorithms, which I culled from Wikipedia.


(k buckets)
Algorithm Stable Time Complexity
Best Average Worst
QuicksortN Ω(n2) Θ(n log n) O(n log n)
Merge sortY Ω(n log n) (typical)
Ω(n) (natural variant)
Θ(n log n) O(n log n)
TimsortY Ω(n) Θ(n log n) O(n log n)
HeapsortN Ω(n log n) (distinct keys)
Ω(n) (equal keys)
Θ(n log n) O(n log n)
Bubble sortY Ω(n) comparisons,
Ω(1) swaps
Θ(n2) comparisons,
Θ(n2) swaps
О(n2) comparisons,
О(n2) swaps
Selection sortN Ω(n2) comparisons,
Ω(n) swaps
Θ(n2) comparisons,
Θ(n) swaps
О(n2) comparisons,
О(n) swaps
Tree sortY Ω(n log n) Θ(n log n) О(n2) (unbalanced)
O(n log n) (balanced)
ShellsortN Ω(n log n) depends on gap sequence О(n2) (worst known gap sequence),
O(n(log n)2) (best known gap sequence)
Bucket sortY* Ω(n + k) Θ(n + k) О(n2)
Radix sort
(d digits,
each from 0..k)
Y* Ω(d(n + k)) Θ(d(n + k)) О(d(n + k))
Counting sort
(max value k)
Y Ω(n + k) Θ(n + k) O(n + k)
* If underlying sorting algorithm is stable.