Coldbox and VueJS untangled

Category: Coldbox (Page 2 of 3)

Arguments in arguments…

I have to admit. This is not the most useful post I ever wrote, but today I discovered something funny but interesting when I tried to fix some small bug. I was working with the bcrypt module. If you don’t know what this module is doing: it is a very secure way for hashing passwords, and since checking the validity of your password is relatively slow it is quite useful to prevent password cracking. Before diving into bugfixing let’s see what bcrypt is doing. It is a coldbox module and only has a few relevant functions:

  • hashPassword(password, [ workfactor], [salt]) which generates a password hash based on a salt and a workfactor. If you don’t supply a workFactor or salt, the coldbox module will generate a salt with a default workfactor of 12. The higher the workfactor, the longer it takes to check for a valid password. (on my system a workfactor means it takes 200 milliseconds to check for a valid password.
  • checkPassword( candidate, bCryptHash) will check a password candidate agains a (stored) bcryptHash.
  • generateSalt( workFactor ) will generate a salt, based on a workFactor. Increasing a workfactor by 1 will mean it takes double the time to check your bCryptHash. This way you can prevent password attacks, because generating and checking is relatively slow.
Continue reading

Protecting your passwords with bCrypt.

We all know. We should never ever store a plaintext password in a database. If a hacker gains access to your data you will be in serious trouble. There are many ways to protect your data, but at least you should make sure your passwords are not readable. In the past we did this by some simple hashing, but modern computers are so fast it is easy to do some password cracking. In time it even gets easier because processors are becoming faster and faster. Another disadvantage: simple hashing will reveal some records with the same passwords. These are often the easiest to guess or crack by brute force. So we need something better.

Coldbox has a nice little module called bcrypt, which is just a wrapper to the jBcrypt java library which is a Java™ implementation of OpenBSD’s Blowfish password hashing code. Wikipedia has a nice description of the bcrypt password hashing algoritme. Bcrypt hash some strong points:

  • generating a hash for the same string will always return different results
  • comparing a password candidate with the stored hash is relatively slow, which makes brute force attacks harder.
  • the hash can be generated with different workfactors. The higher the workfactor, the more time it takes to compare your hash with a password candidate. By increasing the workfactor in time you can account for faster processors, so brute-force attacks remain unattractive.
Continue reading

qb: Autodetecting your bind variables in SQL

In an ideal world, everyone is using qb or quick, and you really don’t know what a bind variable is. Before you discovered this ideal world, maybe you were using queryExecute and were executing queries like this one.

var q =queryExecute("Select * from users where userId = #url.UserId#");

This kind of code ( don’t do this in production ! ) is wide open for sql injection attacks. This post is not about sql injection, so we assume you were already so smart to use queryparams, so something similar to this.

var q = queryExecute(
  sql="Select * from users where userId = :myId",
  params =  { myId: { value = rc.UserId, cfsqlType = "integer" }
)
Continue reading

Cfcompile to the rescue (part 2)

A few days ago I blogged about some annoying lucee or coldbox behaviour. On syntax errors in components often I didn’t get feedback on the offending file or line numbers. This makes it very hard to debug your application if you made changes in several files at once. After my post I was contacted by Zac Spitzer who asked me if I could file a bug. I already did this a few months ago, but they couldn’t reproduce my case. So we talked about this bug and I digged a little deeper to find out what was wrong.

Continue reading

Cfcompile to the rescue

This is a story about sloppiness, dislexia, or maybe my touch typing skill are just lacking when coding. I also hear friends telling me their cat is sleeping on the keyboard. To add to this disaster, Lucee is not very helpful when trying to decipher my typo’s. I wonder if you ever saw a screen like this:

We all see these ugly screens sometimes, but usually they provide some information on an error. But not this time…

Continue reading

CbValidation: UDF or Customvalidator?

Yesterday someone had an interesting use case for the cbvalidation library. I presented at ITB2020 about cbvalidation, and I’ve contributed some code so I thought it had no secrets anymore. But when trying to solve this case I discovered cbvalidation still had some hidden lines for me. When discussing this validation problem we tried to solve it with UDF validators, but -spoiler alert-finally we agreed it was not powerful enough. So time to build a CustomValidator, which is a lot easier than you might think.

Continue reading

Input validation with full null support

Adobe introduced full null support in ColdFusion 2018. Before 2018 null values returned by databases and external systems were converted to empty strings. This behaviour made it almost impossible to distinguish between empty strings and null values, and also caused issues with serialization and deserialization. You also had to take special precautions to insert or update null values in a database. Interaction with Java, including CFORM based hibernate could also result in returned null values so we always had te be very careful when trying to handle these dreaded nulls.

Lucee already has full null support since many years, but just as with the latest ACF version, you have to enable this in the administrator, just to stay compatible with older versions of ACF.

So, because of all these null handling issues, why not enable full null support? That’s what we imagined when creating our latest REST based application. But before hurrying to your admin panel better think if it will break something.

Before the Modernize or die times as promoted by Ortus Solutions there were many ways to find out in Coldbox if all input variables existed. Let me give these two JSON examples, both are used for the creation of a user in the body of a post request:

//first example, customer_id as a null value because customer is not selected yet
{
    "customer_id": null,
    "username": "wdb",
    "password": "topsecret"
}
//second example, customer_id omitted because customer is not selected yet
{
    "username": "wdb",
    "password": "topsecret"
}

When we post this userdata, I want to validate if my customer_id is there so I can populate some required customer field. When null support is not enabled we have a few options to check if we have a usable customer_id.

function createUser( event, rc, prc ) {
  //option 1
  if ( event.valueExists("customer_id") ){
    //....
  }
  //option 2
  if ( structKeyExists(rc,"customer_id") ){
    //....
  }
  //option 3
  if ( !isNull(rc.customer_id) ){
    //....
  }

The first options seems to make sense. Event.valueExists is a way to check if my customer_id is a value in my request collection.
The second options is slightly more low level, it just checks the request collection for the existence of customer_id.
The third option is a little bit more direct. It just checks if rc.customer_id is not null so I can continue.

So it seems it doesn’t matter which method I use. But now I enable full null support, and the whole landscape is changing. In the previous part I just assumed the key should be there, or not be null.

But now I have to know what my frontEnd VueJS developer is doing. Is he sending a null value for customer_id if there is no customer selection yet? Or is he only sending values in the JSON body which already have a value? This will make a lot of difference .

If my frondend developer is sending null values and I enable null support in CFML my event.valueExists and StructKeyExists() checks are completely useless, because my customer_id variable now does exist in the request collection. The problem here is it’s value is useless, because I can’t retrieve a required customer based on a null value. So the only safe check now is the !Isnull(rc.customer_id) .

The situation is still a bit different if you also want to be able to update a database based on the input of a null value. In that case you have to check for both Event.ValueExists AND IsNull.

The above examples seem quite trivial, but a word of warning is appropriate here. You really have to know how your frontend application should handle these null values. Are you validating ALL properties, or only the properties which have been entered by the user?

A second important point is the handling of nulls in some of your supporting libraries. We failed a lot of tests because one of our libraries tried to determine the datatype of our input automatically. Since null values have no datatype the library failed. This was fixed very soon, but especially when using some older libraries or modules you really should take a close look at the code when possible.

Inserting NULL values in qb

I can highly recommend the qb library for all kind of database manipulations, for querying and data definitions. Qb hides a lot of complexities for database actions, and abstracts away differences between database engines.

Although very powerful, some options are really well hidden in the documentation or the source code. Recently I wanted to update a database table with null values. The normal syntax for updating values in a database table is:

query.from( "users" )
    .update( {
        "email" = "foo",
        "name" = "bar"
    } );

If you have more complex requirements like inserting date values in the correct formats, you can specify query param options, e.g

query.from( "users" )
    .update( {
        "email" = "foo",
        "name" = "bar",
        "updatedDate" = { value = now(), cfsqltype = "CF_SQL_TIMESTAMP" }
    } );

This query param syntax comes in handy when inserting NULL values. As we all know older versions of Adobe Coldfusion and Lucee can’t handle null values very well:

query.from("user")
		.whereId( 10 )
		.update( {
			manager_FK = { value = "", null=true },
		} )

If you are using Lucee with full Null support you can leave out the null parameter, e.g

query.from("user")
		.whereId( 10 )
		.update( {
			manager_FK = { value = null },
		} )

Commandbox-migrations and SQL server

Cfmigrations is a nice tool to describe database changes and version them with your application code. It comes in two flavours as a forgebox package: cfmigrations if you want to manage your database changes from within you application and commandbox-migrations if you want to do the same from within commandbox. Actually the commandbox version is just a wrapper around cfmigrations. The forgebox description gives a nice overview how to use this tool.

How to use: some MSSQL and java problems

So why this post, if the manual is already there? Because it doesn’t always work out of the box, and you have to know how to use this tool in commandbox. So let’s start.
First we are going to install commandbox-migrations. Start up commandbox in your homedir and execute

install commandbox-migrations

If you want to start using migrations, you have to initialize it. This will not do any database activity yet, it just creates the right keys in your box.json.

migrate init

The following entry will be created in your box.json

    "cfmigrations":{
        "schema":"${DB_SCHEMA}",
        "connectionInfo":{
            "password":"${DB_PASSWORD}",
            "connectionString":"${DB_CONNECTIONSTRING}",
            "class":"${DB_CLASS}",
            "username":"${DB_USER}"
        },
        "defaultGrammar":"AutoDiscover"
    }

Save yourself some trouble and change your default grammar immediately, because the Autodiscover probably doesn’t work within commandbox. Your options (as documented here) are: MSSQLGrammar, MySQLGrammar, OracleGrammar and PostgresGrammar. We choose MSSQLGrammar. As you can see from the box.json, most options are populated with environmental variables instead of real values (the values surrounded by ${} ). This is a good practice so your credentials don’t end up in you code, and you probably need different values for development and production. To use environmental variables in your commandbox environment you can install the commandbox-dotenv package. Now you can create your environmental variables in a file called .env in your root directory. Please make sure you exclude this file from version control!!!

Now you need to set your environmental variables DB_PASSWORD, DB_USER, DB_SCHEMA, DB_CONNECTIONSTRING and DB_CLASS. Values for password and user are obvious, but what about the other values? In my environment I can leave the DB_SCHEMA empty, but I need values for DB_CONNECTIONSTRING and DB_CLASS. If you don’t know these values yet, you can find these values by creating a a datasource in your Lucee Admin. If you edit this datasource, you will find some useful info at the bottom of this screen, like this

datasource properties

So I entered all values for the Microsoft driver in my .env file and tried to install the tables necessary for cfmigrations (by default called cfmigrations. I executed this:

migrate install

This will NOT work. You have to reload commandbox first, to retrieve your added (or changed) environmemtal variables. You can do this just by executing the command reload. If you forget to reload, you will probably get a java.lang.NullPointerException. But after reloading and trying to create a valid MSSQL connection we will enter Microsoft/Java problem territory

The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: “java.security.ProviderException: java.security.KeyException

For some reason the Microsoft driver is not very cooperative in a commandbox environment, although I have no issues when used in my Lucee server. The commandbox gitbook manual has some info on hitting databases from commandbox: https://commandbox.ortusbooks.com/task-runners/hitting-your-database and indeed:

Microsoft SQL Server Issues
If you are getting SSL related exceptions when trying connecting to an MS SQL database using the Microsoft SQL Server (JDBC4) driver (com.microsoft.sqlserver.jdbc.SQLServerDriver), try using the jTDS driver (net.sourceforge.jtds.jdbc.Driver) instead.

So, that’s really a waste of time if you try to use cfmigrations with SQLServer for the first time! Actually I ‘ve used it a zillion times with older versions of commandbox back in the Lucee 4.5 days without any problems. But hey, problem solved! I changed my settings in .env and reloaded commandbox

jtds instead of the microsoft driver

If I execute migrate install again, cfmigrations is ready for some real database modifications, which I will describe in a later post.

Cfmigrations really is a very handy tool. It is nice if you can reconfigure your database tables directly from commandbox, but you really need some extra info in advance, such as:

  • how to work with commandbox-dotenv
  • why is a SQL driver misbehaving in a commandbox environment, and more important: how to avoid this by using the jTDS driver.

I am sure the process is a lot easier with some other databases, but I hope this write-up helps. If you really want to avoid all the trouble in configuring your database, you can also use cfmigrations from within your application, where you have your datasource already available.

« Older posts Newer posts »

© 2021 ShiftInsert.nl

Theme by Anders NorenUp ↑