Overview

Project Nashorn – JavaScript on the JVM

No Comments

Suppose you have a password strength checker in your user interface to help users choose secure and easily remembered passwords. Since estimating password strength involves more than just checking character classes you use a library like Dropbox’s zxcvbn which avoids a few of the mistakes that ebay recently made. If you did this, then you are on the right track, but are you validating the password strength additionally on the server to reject weak passwords? It is common knowledge that one cannot trust user data and therefore needs to validate everything on the server. But how do you do this when the password strength check is written in JavaScript and the server is running a Java application?

Java 8 introduces a neat and performant way to solve this issue: Compile JavaScript to bytecode and execute it natively on the JVM! The eighth version of Java ships with a JavaScript engine named Nashorn. Nashorn is available through the JSR-223 scripting APIs and can be used in any Java 8 application with a few lines of code. The following listing shows the classic Hello World example with Nashorn. Note that it can be executed without any configuration or additionally libraries.

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
 
String js = "print('Hello World!');";
engine.eval(js);

Short Introduction to JSR-223

JSR-223 is the specification request for scripting support on the Java platform. The specification describes how scripting engines such as Nashorn are located, retrieved and how bindings between variables in the scripting language and Java objects are created. Additionally, the specification also describes concepts such as script contexts, scopes and more.

A ScriptEngine is one of the core concepts that is being used to interact with the underlying language runtime. ScriptEngines can be retrieved via a ScriptEngineManager which in turn locates engines via a service provider mechanism. The service provider mechanism being used is java.util.ServiceLoader (JavaDoc). This mechanism has been introduced with Java 6 and works by scanning the class path for configuration files. Java 8 ships with such a configuration file. This is the reason why Nashorn can be used without any manual configuration.

The Password Strength Check In Detail

Let’s take a detailed look on how one might implement the password example with Nashorn.

Step 1) Add the zxcvbn dependency

To implement the password check on the server side the zxcvbn library needs to be on the class path. This can be done quite easily with the help of the WebJars project. WebJars package client-side dependencies such as jQuery, Angular, zxcvbn and many more into JAR files. A dependency to such a JAR file can be managed with the standard Java tools, e.g. Maven, Ivy or Gradle. The following listing shows the necessary addition to the Maven pom.xml in order to use zxcvbn. Once added to the POM the file /META-INF/resources/webjars/zxcvbn/1.0/zxcvbn.js will be on the class path and can be read via standard Java mechanisms.

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>zxcvbn</artifactId>
    <version>1.0</version>
</dependency>

Step 2) Run the Script

Now that the script is on the class path it can be executed with Nashorn. To run the script and check passwords, a few things need to do be done:

  • retrieve the Nashorn ScriptEngine via the ScriptEngineManager
  • evaluate the zxcvbn script in the context of the engine so that it registers itself globally as it would in a browser environment
  • run a password through the globally registered zxcvbn function and turn the return value into a Java POJO
 public class StrengthChecker {

private static final String ZXCVBN_PATH = "/META-INF/resources/webjars/zxcvbn/1.0/zxcvbn.js";

private final ScriptEngine engine;

public StrengthChecker() {
// 1.
ScriptEngineManager manager = new ScriptEngineManager();
engine = manager.getEngineByName("nashorn");

More content about Flexible Architectures

Comment

Your email address will not be published. Required fields are marked *