Blade 2.1 - Razor 3 support

I’ve pushed Blade 2.1 out to NuGet. This release updates the MVC references to MVC5, and the Razor references to Razor 3.

This release also uses the latest bits for Sitecore NuGet, which resolve some issues with local IIS site connections.

Sitecore Data Architecture

Introduction

There are many times where you need to extend the Sitecore data architecture in some way. One of the most obvious, and most used, is attaching an event handler to one of the item events (e.g. item:saved, item:renamed) but this is not by any means the only way to manipulate items before they get to the database.

This blog post came out of a discussion I had with Alex Shyba about the DataEngine, a few hours on a plane, and a lot of decompilation. I’m going to attempt to show what happens when an item gets saved and where you can plug into that.

The entry point

The most high level API is of course the Item class. Saving an item using this API is very simple:

using(new EditContext(item))
{
    item["MyField"] = "newValue";
}

When the EditContext goes out of scope, this causes item.Editing.AcceptChanges() to be invoked, and our journey down the rabbit-hole begins there.

The Item Manager

Our next step is the highest level item data API in Sitecore: the ItemManager. At first blush ItemManager appears to be a rather ugly giant static class, with tons of manipulaton methods: SaveItem, AddVersion, etc. However, it’s not as bad as it looks. ItemManager is basically a static facade around the current ItemProvider.

The Item Provider

Here’s where things get interesting. You can register multiple item providers in the config under itemManager/providers. While this appears to provide a lot of power as an extension point - being able to plugin your own high level provider - it unfortunately seems to be rather ungainly. If multiple providers are registered you can access them directly using ItemManager.Providers, but the other ItemManager methods only execute against the default provider. You could replace the default provider with your own, but this is less than ideal as it can lead to contention for whose item provider gets used if more than one module wants to extend using it.

Extension points aside, the ItemProvider is the most broad data API Sitecore provides. It deals in high level objects and abstracts lower level concepts like databases and item definitions away. Most all methods in the ItemProvider result in invocations of the next lower level construct, the DataEngine.

UPDATE: Nick Wesselman pointed out that some queries will bypass the Item Provider and go directly to the Data Engine. This gist has some examples of the types of things that bypass the Item Provider. In light of this I’d say the item provider is generally not a good candidate for extending things.

The Data Engine

DataEngine (generally accessed by databaseObject.DataManager.DataEngine) is a very interesting component for extension. Unlike the item provider, the DataEngine is database-specific. This is also the layer at which item event handlers (e.g. item:saved) are processed, but more interestingly is also a place where you can hook events in an uninterruptible fashion. Regular event handlers, such as item:saved, are vulnerable to being disabled when someone scopes an EventDisabler. Generally this is good, as events are disabled for performance reasons during things like serialization bulk load operations. But occasionally, such as in Unicorn, you need an event handler that cannot be disabled. Having a Unicorn event not fire would likely mean data being lost.

The internal architecture of DataEngine works something like this:

  • An engine method gets invoked
  • The engine creates and initializes an DataEngineCommand<> object, using a stored prototype of the command
  • The DataEngineCommand has its Execute method invoked.

The EngineCommand is a generic type, and each action that the engine can take has its own implementation - for example, there is a Sitecore.Data.Engines.DataCommands.SaveItemCommand class. Each of these command types is bootstrapped by a prototype system on the DataEngine itself. The engine, by way of its Commands property, stores copies of each command type. When a new command is needed, the existing prototype command is cloned (Clone()), initialized (Initialize()), and then used to execute the action. These prototypes are settable, including via configuration, so this allows you to inject your own derived implementation of each command and thus inject ‘event handler like’ functionality into the DataEngine.

Item Buckets utilizes this type of functionality injection, replacing the AddFromTemplatePrototype with its own extended implementation. This is the relevant section of Sitecore.Buckets.config:

  <database id="master" singleInstance="true" type="Sitecore.Data.Database, Sitecore.Kernel">
    <Engines.DataEngine.Commands.AddFromTemplatePrototype>
      <obj type="Sitecore.Buckets.Commands.AddFromTemplateCommand, Sitecore.Buckets" />
    </Engines.DataEngine.Commands.AddFromTemplatePrototype>
  </database>

This same functionality could be used to inject non-disableable event handler type functionality into other events, for example by replacing the SaveItemPrototype. Unfortunately this method also suffers from possible contention issues if multiple modules wished to patch these commands, so be careful when using them.

The DataEngineCommand

Once the DataEngine creates and executes a command, the command generally does two things:

  • Pass its task down to the Nexus DataApi to be handled
  • Fire off any normal item event handlers (item:saved), as long as events are not disabled

Most of the methods on DataEngineCommand are virtual so you could extend them. The most obvious candidate, of course, is the DoExecute method that performs the basic action of the command.

Further down the rabbit-hole we arrive to the Nexus APIs.

The Nexus DataApi

The Nexus assembly, due to it containing licensing code I believe, is the only obfuscated assembly in Sitecore. This makes following what the data API is doing rather difficult, but I’m pretty sure I traced it back out as a call to the databaseItem.DataManager.DataSource APIs, which thankfully are not obfuscated. It’s worth noting that the Nexus APIs appear to also be using a separate command-class based architecture internally. Given the sensitive nature of the Nexus assembly however, I would look elsewhere for extension points.

The DataSource

The Sitecore.Data.DataSource appears to largely be a translation layer between slightly higher level APIs, where things like Item are used, and the low level API of the data providers (which use constructs like IDs and ItemDefinition instead). The data source is very generic and does not appear to be designed for extension, which is fine because we can extend both above and below it.

Methods within DataSource eventually make calls down to static methods on the DataProvider class.

The Data Provider

There are two faces to the DataProvider class. The internal static methods that the DataSource is invoking are helper methods that invoke non-static methods on all of the data providers attached to the database. (Yes, you can have multiple data providers within the same database, which may not even look at the same backend database at all…hehe) The actual data provider instances are the lowest level data APIs in Sitecore. They deal with primitive objects and have a lot of unspoken rules about them that make them tougher to implement than most other extension points. However they are also the most powerful extension point there is. Using a data provider you can manipulate the content tree in nearly any fashion for example Rhino, a data provider that makes serialized item files on disk appear to be real content items in Sitecore.

You’re still reading this?

Hopefully this is a useful post for some crazy nuts like myself who like to bend the guts of Sitecore. It’s definitely a long and byzantine road from saving an item to it getting to the database. Rather amazing that Sitecore is as fast as it is with all of these layers. Part of me suspects that some are baggage from Sitecore 4 for backwards compatibility ;)

A Fury of Updates

Put me on a plane to the Sitecore MVP Summit and I’m going to write software! All of these updates are available on GitHub for source and NuGet for packages.

Synthesis.Blade.Ninject

This is an extension to Synthesis.Blade that enables automagical constructor dependency injection to any presenter using the Ninject IoC container. I previously blogged about how to do this (it’s not that complex) but now doing DI with Blade is as simple as a NuGet package. Simply wire up Ninject with your dependencies, add some dependencies to a presenter constructor, install this package, and you’re good to go. Here’s a simple example of a presenter using DI to get a repository dependency:

public class TestPresenter : SynthesisPresenter<TestModel, ITestTemplateItem>
{
    private readonly ITestRepository _repository;

    // this constructor parameter will be automatically set by Blade via Ninject
    public TestPresenter(ITestRepository repository)
    {
        _repository = repository;
    }

    public override TestModel GetModel(IView view, ITestTemplateItem item)
    {
        var model = new TestModel();

        model.Frob = _repository.GetFrob(item);

        return model;
    }
}

Note: It’s trivial to implement the same constructor injection with a different IoC container, or without using Synthesis integration. Take a look at the source for Synthesis.Blade.Ninject and it should be pretty obvious what to do :)

Note2: Make sure to use the above Synthesis.Blade 7.0.1 configuration file, or the installation may not work correctly and patch the wrong thing.

Blade 2.0.1

This is a minor release with enhancements to testability and bug fixes.

  • The “Page” property on IView is now marked as obsolete, as it exposes a lot of untestable data to a presenter
  • IView now has a ViewContext property that exposes the HttpContextBase for the current request, enabling testable access to request and response data within presenters
  • Fixed a bug that caused unexpected presenter resolution when using inheritance in model types (IView became covariant in Blade 2, which meant that IView<BaseClass> became similar to IView<DerivedClass>, and the base class presenter might be selected first in some cases) - fix courtesy of @gobiner

Synthesis 7.0.1

This is a minor release that corrects an oversight in 7.0.0 where some of the new field type interfaces did not have setters for their values. This prevented editing items when using field type interfaces. Bug report courtesy of @gobiner.

Synthesis.Blade 7.0.1

This is a minor release that resolves an issue with the default configuration file if multiple patches were present to the Blade PresenterFactory. To upgrade an existing installation, simply edit Synthesis.Blade.config and change the presenter factory patch line to read like so (changing the ‘instead’ attribute):

<presenterFactory patch:instead="*" type="Synthesis.Blade.Configuration.SynthesisPresenterFactory, Synthesis.Blade" />

Make Web Forms for Marketers use a regular connection string

One of my pet peeves about the Sitecore Web Forms for Marketers module is that it manages the forms database connection string in its own config file, instead of the regular ConnectionStrings.config file.

Fortunately this is easy to fix if you want to manage all your connection strings in one place. First, you need to override the default WFMDataProvider like so:

Then, you modify the data provider declaration in App_Config\Include\forms.config (replace the namespace and assembly with wherever you place the class above in your project):

Finally, simply add a connection string named forms (or whatever name you configured in forms.config above) to your ConnectionStrings.config and you’re good to go!

Sitecore preview mode and loading jQuery

It seems like most folks these days are using jQuery on their sites. Sitecore, in fact, uses jQuery for the page editor UI. I discovered an interesting case where it can conflict with your own jQuery version that I thought I’d share.

The scenario where it happens is this:

  • You are in preview, page editor, or debugger mode (any mode where the webedit toolbar renders on the site)
  • You are loading your jQuery library in the page header and not the footer (note: you should load it in the footer if it’s at all possible)

jQuery has a feature called noConflict that is designed to allow you to isolate it from other libraries, such as Prototype, that also claim the “$” global variable. The feature can also be used to run two versions of jQuery on the same page, and Sitecore in fact does exactly this. However, the case that noConflict does not prevent is one where a second copy of jQuery is loaded on top of an existing one.

What happens here is that your jQuery loads in the heading, then Sitecore loads its jQuery and calls noConflict on it. Unfortunately, the loading of Sitecore’s JS overwrites the global jQuery variable, resulting in this mess:

  • jQuery = Sitecore jQuery (1.5.5 for SC7 Update-1, pretty old)
  • $ = your jQuery

Now load a jQuery plugin that uses an IIFE to load itself like:

(function($) {
    // plugin load code here
})(jQuery);

Yeah that’s right, the plugin invokes its function passing in jQuery aliased as $. Which means that the plugin just loaded to Sitecore’s jQuery, not yours! Now if you invoke the plugin you’ll see that it’s undefined in your jQuery!

Fortunately it’s relatively easy to manually fix this issue. You simply need to:

  • Save your jQuery variable immediately after you load it:
    <script>var my_jquery = jQuery;</script>
  • Define the webedit placeholder explicitly on your layout, so you can control where Sitecore will load its version of jQuery:
    <sc:Placeholder runat="server" Key="webedit"/>
  • Set the global jQuery variable back to your saved jQuery immediately after the webedit placeholder definition:
    <script>jQuery = my_jquery;</script>
  • It’s safe to let this code run even when not in preview mode, as it will simply have no effect if Sitecore does not load its jQuery. Of course you can also render it only when !Sitecore.Context.PageMode.IsNormal as well if you want clean output.

If you can put your copy of jQuery in the footer, you don’t need to resort to any of this hackery. Hope this helps someone :)

Announcing Synthesis 7

Synthesis 7 is now available on NuGet. This version brings a number of new features and bug fixes largely aimed at supporting unit testing of sites that are built with Synthesis. Version 7 is compatible with Sitecore 7 Update-1 and Update-2.

Fully mockable generated item classes

Previous versions of Synthesis would generate classes that had concrete field types, such as RichTextField, that were strongly tied to the Sitecore item APIs or search APIs. This prevented easily creating mock versions of the class for testing purposes. Synthesis 7 changes that by allowing you to define both a private concrete field type mapping and and public interface mapping, such as this:

[IndexField("title")]
public ITextField Title {
    get { return new TextField(/* ... */);
}

Now each field can be easily mocked with a mocking framework of your choice, enabling you to create totally Sitecore API free instances of Synthesis items. For example, using Moq:

var item = new Mock<IFooItem>();
item.SetupGet(x => x.Title).Returns(new TestTextField("isn't this nice?"));

string result = item.Object.Title.RawValue; // "isn't this nice?"

But wait! What about those pesky metadata properties like statistics, database, and editing? Those are annoying, huh. Well Synthesis 7 uses adapter classes to make those mockable too.

public IDatabaseAdapter Database { get; }

It’s very easy to add a public interface to a field type mapping; you simply add an interface attribute to the mapping:

<map field="Single-Line Text" type="Synthesis.FieldTypes.TextField, Synthesis" interface="Synthesis.FieldTypes.Interfaces.ITextField, Synthesis" />

New testing package

There is now a Synthesis.Testing package on NuGet that contains some dummy field type implementations to help you write cleaner mocks of Synthesis item types. The TestTestField class referred to in the Moq example above is part of the testing package.

Injecting custom field implementations on a per-template-field basis

Previously you were able to map a Synthesis field class to a Sitecore field type. Synthesis 7 enables you to get more specific and map a field class to a specific field on a template. This enables you to provide custom behavior for specific fields.

<templateFieldMappings hint="raw:AddTemplateMapping">
    <map template="Content Section" field="Content" type="Synthesis.FieldTypes.TextField, Synthesis" interface="Synthesis.FieldTypes.Interfaces.ITextField, Synthesis" />
</templateFieldMappings>

The template specification can be the template name, full path, or ID interchangeably. The field can be either the field name or field ID.

Better missing field messages

If you’ve used Synthesis long, you’ve probably seen this one. You add a template field, generate your model, and forget to publish the field. Suddenly you get a really helpful “Parameter cannot be null” error that doesn’t tell you anything about the field name that actually caused it. Synthesis 7 fixes that problem, and reports the field name that was missing instead of a generic error message.

Bug fixes

  • Modified default behavior of synthesis.axd. In Synthesis 5-6, if the model was detected as synchronized, no option to force a rebuild would be available. Problem is, configuration changes (e.g. changing the root namespace) do not invalidate the template signatures - so there were times when a ‘synchronized’ model would need to be force rebuilt. In Synthesis 7, the handler always rebuilds the model even if synchronization is detected.
  • Synthesis will no longer generate invalid C# code when faced with a template or field name that starts with a number. Leading numbers are automatically prefixed with _ so as to retain valid C#.
  • Fix media item URL generation error when LinkProvider has AlwaysIncludeServerUrl enabled. Previously, links like /http://foo/~/media/bar would be generated. Fix contributed by Dave Peterson
  • Removed a hack that allowed the LINQ extension GetSynthesisQueryable() to work, because it was fixed in Sitecore 7 Update-1.

Breaking changes

  • Due to the new adapter classes, code that uses the Database property may break. The adapter class returns Synthesis types, whereas the Synthesis 6 version returned Sitecore Item instances. This enables decoupling the IDatabaseAdapter from the Sitecore API.
  • If using interfaces for your object properties (which you will need to manually enable if upgrading), the type of those properties will change. This may break code such as view models that contains fields as properties.
  • Support for implicit field conversions (e.g. to treat a TextField as a string) have been removed. These do not work when using interfaces, and generally are a bad idea because they can allow unexpected behavior (is an implicit conversion to use a raw value? field renderer?).
  • Support for the FileListField (File Drop Area) field type has been removed
  • Support for the WordDocumentField field type has been removed
  • The IFieldMappingProvider interface signature has changed to enable injecting custom field types on a field level. Custom providers may need minor refactoring.
  • Synthesis.Blade: the signature of the SynthesisPresenter.GetItem() method has changed from protected to public (a breaking change for all presenters based on this). Unfortunately, this was by far the simplest and cleanest avenue to allow for injecting arbitrary Synthesis item data sources for testing purposes.

Upgrading

Upgrading to Synthesis 7 is a process that takes a bit of work.

  • First, upgrade the NuGet package to Synthesis 7

  • After upgrading the NuGet package, you should remove the field mappings in Synthesis.config to the removed Word Document field and File Drop Area field types. The Word field mapping may not exist depending on what version you’re coming from.

      <map field="File Drop Area" type="Synthesis.FieldTypes.FileListField, Synthesis" /> <!-- remove this from Synthesis.config -->
    
  • Next, you will need to regenerate the Synthesis model. Do not build the project at this point, because the model format has changed in Synthesis 7 and the existing model will be full of build errors. Hit /synthesis.axd and force a regeneration, which will remove any build errors not caused by a breaking change as outlined above.

    • If some sort of global handler (such as a httpRequestBegin pipeline handler) is causing an error before you even get to synthesis.axd temporarily disable it for the purposes of regenerating the model.
  • By default, a Synthesis 7 upgrade will not enable using interfaces for field types (unless you overwrite Synthesis.config during the install, which is not recommended). Should you wish to enable interfaces, simply look at the default config file and merge the interface attributes in under <fieldMappings> to your config, then regenerate.

  • If using Synthesis.Blade, you will need to change the visibility on GetItem() for any presenters that use SynthesisPresenter as their base class to public, instead of protected.

  • Verify that the case of your content search config patch at the bottom of Synthesis.config matches the case in your Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config. The case of the default config changed in Update-2, but depending on how you upgraded yours might not have. See this blog post for details as to why this is necesary. If the case is incorrect, Synthesis LINQ queries will not work correctly.

  • Fix any remaining build issues caused by breaking changes (if any), and test the site.

Feedback

I’d love to hear from you if you have trouble or ideas. Send me an issue on GitHub!

As always, the Synthesis source is available under the MIT license, so feel free to hack away - and send me a pull request ;)

Announcing Blade 2

I’m happy to announce that Blade v2 is now available from NuGet. There are some very nice new features in this release.

MVC4 Razor APIs instead of RazorEngine

Blade 2.0 replaces the RazorEngine library with directly calling MVC4 APIs. Doing this is much cleaner (and faster!) than the previous Razor implementation. This does introduce some minor breaking changes so read up before you upgrade.

  • Useful errors with source context if there’s a syntax error or runtime error in a razor file. This was a major issue with previous versions of Blade that made razor errors difficult to debug.
  • Full support, including IntelliSense, for using @model to declare the model type in razor views instead of the much more verbose @inherits RazorRendering<TModel> previously required. The old way still works fine too.
  • The BladeHtmlHelper is gone, replaced by the normal MVC HtmlHelper - note that pieces of the helpers that do not make sense in a pseudo-MVC context, such as ActionLink, may behave unpredictably.
  • View resolution follows the conventions of the MVC view engines that are registered. This means that path resolution is a bit different:
    • Html.Partial() will require absolute paths (~/Foo/Bar/Baz.cshtml) unless you are storing your Razor files in /Views like MVC does
    • When statically including Razor renderings with the RazorTemplate web control, you must add .cshtml on the end of view paths, whereas previously that was optional
    • Razor layout paths are unchanged from previous behavior: they can be relative, and you need .cshtml on them
    • You should be able to plug in whatever view resolution logic you desire by adding in your own view engines in Global.asax just like with MVC sites

Form support and model binding!

Presenters can now handle postback in a clean fashion by using ASP.NET MVC model binding to bind posted values to your ViewModel automatically. There is also explicit support for handling XHR (AJAX) postbacks separately, enabling easy creation of simple callbacks to the same page that return JSON data.

  • MVC model validation attributes (e.g. [Required]) and validation controls are fully supported for Razor views, as are MVC HTML helpers (@Html.TextBoxFor(x=>x.MyStringProperty), for example). User Controls and Web Controls support validation, but they do not have ModelState to pass it around to so you’d need to manually parse the validation result in the presenter for those.
  • To support postback, if using a SitecorePresenter or SynthesisPresenter, simply override the HandlePostBackWithModelBinding method. The method is invoked if HTTP POST is requested, and model binding is automatically executed. Similar methods exist for XHR and non-automatic-modelbinding for both.
  • The postback handling occurs immediately after the OnLoad event just like web forms usually does for submit event handlers. You can assume that GetModel() will have already been called on the presenter.
  • Adding custom ModelBinders in Global.asax, just like in MVC, should work perfectly.

Unit testable presenters

In Blade itself, the SitecorePresenter has been modified to allow injection of a custom Item as the data source of the presenter (via the SetDataSource() method), enabling you to decouple it from data source resolution logic. However, you probably should not be testing with Item instances, as those require a lot of Sitecore API presence. To get around this issue, Synthesis.Blade’s SynthesisPresenter enables injection of a custom Synthesis item interface directly into its GetItem method for completely Sitecore-independent tests! Check out this trivial example of testing a SynthesisPresenter, using Moq:

var item = new Mock<ITestTemplateItem>();
var view = new Mock<IView>();

// todo: setup mocks appropriately

var presenter = new TestPresenter();

var model = presenter.GetModel(view.Object, item.Object);

// todo: assert something about the resultant model

Testing limitations

Views are not particularly testable due to them using the MVC Razor engine, which requires a web context to execute. Hypothetically you could write tests against them using a web-based test runner, but it seems that most people do not recommend testing the view due to the relative fragility of the tests involved.

Upgrading

To upgrade from Blade 1.5 to Blade 2.0, simply upgrade the NuGet package. You should definitely test all of your razor views after the upgrade to make sure they are running correctly against the new MVC-based razor implementation. If you are not using razor, the upgrade should be pretty much seamless.

Because Blade uses XDT-transformation-based installation routines, you will need NuGet 2.6 or later to install it.

If you are also using Synthesis with Blade, you will need to upgrade to Synthesis/Synthesis.Blade 7.0 to be compatible with Blade 2.0.

Feedback

I’d love to hear from you if you have trouble or ideas. Send me an issue on GitHub!

As always, the Blade source is available under the MIT license, so feel free to hack away - and send me a pull request ;)

Sitecore 7 Update-2 and Synthesis 6

Sitecore 7 Update-2 was released today, and it brought with it a surprise: Synthesis’ LINQ query support broke. Well, that’s unusual for a Sitecore update.

Fortunately it is easy to fix. In the Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config config patch file, Update-2 changes all of the element casing from PascalCase to camelCase. So the old XPath /configuration/sitecore/contentSearch/configuration/DefaultIndexConfiguration turned into /configuration/sitecore/contentSearch/configuration/defaultIndexConfiguration. DOH! Unfortunately for us, XML - and Sitecore config patching - is case senstive. This means the config tweaks made to search in Synthesis.config no longer applied!

The release notes for Update-2 do not mention this casing change, so if you were manually patching you might not catch this. But the stock DefaultIndexConfiguraion.config file available for download on that page, as well as in the zip distro of Update-2, both change a lot of case in the config.

Fixing the problem

Fortunately it’s pretty easy to fix Synthesis running against a re-cased Update-2 config file. At the bottom of your Synthesis.config find the section and replace it with this (or just change :

 <contentSearch>
    <configuration>
        <defaultIndexConfiguration>
            <indexDocumentPropertyMapper type="Synthesis.ContentSearch.SynthesisDocumentTypeMapper, Synthesis" />

            <fields hint="raw:AddComputedIndexField">
                <field fieldName="_templatesimplemented" storageType="yes" indexType="untokenized">Synthesis.ContentSearch.ComputedFields.InheritedTemplates, Synthesis</field>
            </fields>
        </defaultIndexConfiguration>
    </configuration>
</contentSearch>

Dealing with versioning

Unfortunately this leaves Synthesis in a less than optimal situation where the default distribution is more or less Sitecore patch-specific. Synthesis 5, released with Sitecore 7 RTM, only works with RTM. Synthesis 6, released with Update-1, only works with Update-1 due to the moving of a Sitecore class in the update. It requires you to find this blog post to get it to work correctly with Update-2 by way of the patch above. The upcoming Synthesis 7 will have configuration by default for Update-2 - which means it will break if installed under Update-1.

Don’t get me wrong, I love Sitecore 7, but the search APIs are more than a little unstable at the moment for library authors!

Upgrading Sitecore's Password Security with PBKDF2

The problem

A few months ago I read a very interesting article on Ars Technica titled How I became a password cracker. Seriously, go read it. These days it’s astonishing how simple it is to brute force even long, random-looking passwords. That 1337-5p33k p@55w0rd? You might as well use dictionary words because there are rules that check for that. Using a passphrase of english words (like correct horse battery staple)? Well it’s easy to test for combinations of dictionary words too, so those are a lot less secure than they look.

Mitigation

The core problem is that most passwords are stored using hash algorithms such as SHA and MD5 that were originally designed to verify file integrity - so speed was a primary concern. If a hash algorithm is fast, so is brute-forcing passwords that use it. Modern GPUs can compute hashes obscenely fast (spend a bit and you can hit 1 billion hashes per second), so a good way to thwart attackers is simply to use a hash algorithm that is slow. Several algorithms exist that are designed to be utilized specifically for passwords (such as PBKDF2 and BCrypt), and they are all much slower to compute for this very reason.

These algorithms also usually have a “work factor” that allows you to adjust the time it takes to compute the hash, which provides even more future-proofing against even faster password cracking hardware that is yet to be developed.

When would this affect Sitecore?

To be clear this is not a remotely-exploitable vulnerability. It’s also not a Sitecore-specific vulnerability - it affects most all sites running ASP.NET’s Membership provider which until very recent providers (Universal Providers) defaults to the SHA1 hash algorithm to store passwords. In order to exploit what I’m describing here, an attacker would have to gain access to your databases, which they would then use an offline password cracker like oclHashcat-plus to break the passwords to login to Sitecore.

Using PBKDF2 with Sitecore

There’s a class in the .NET framework that implements the PBKDF2 algorithm already, but it does so in a way that makes it difficult to add to a membership provider. There’s a very nice NuGet package called Zetetic.Security that wraps this functionality into a KeyedHashAlgorithm that can be used easily with membership. It’s very easy to install PBKDF2 into a membership provider using it - you have to install the NuGet package and change two configurations.

The only problem is that existing users will be unable to login because the existing hashes are all in SHA1 (Sitecore, and membership’s, default algorithm) and the membership provider now expects PBKDF2 hashes. If there are only a few users you can just reset passwords and be done with it. But if you have an existing userbase, you probably wish you could allow existing users to keep signing in, and new users (or password changes) to convert to PBKDF2. I’ve implemented a prototype extension of the SqlMembershipProvider that does exactly this by allowing the ValidateUser method to attempt SHA1 if PBKDF2 validation fails.

Other uses

The solution discussed in this post was tested against Sitecore, but is a generic method you could use with any .NET app that uses SQL Membership to store user info. I hope this random crypto rant has been useful to you :)

Editing hidden template fields in the page editor

Recently on a project I came across a need to allow editors who were using the Sitecore Page Editor to modify some fields that had no logical place on the actual editor screen. In this case, the fields were relating to page SEO - meta keywords and description among other things. Since these are in the head of the page, there’s no good place to stick an edit frame or custom experience button - they aren’t even part of a rendering placed on the page.

While poking around the WebEdit customization options, I hit on the idea of adding a WebEdit ribbon button that would act as a custom experience button would, and load a subset of the item fields in a content editor window. It turns out this was actually relatively easy.

In the Core database, the default WebEdit ribbon is defined under /sitecore/content/Applications/WebEdit/Ribbons/WebEdit/Page Editor. Under this item are items for each ‘chunk’ in the ribbon, and under that each command button, like this:

tree

To implement your own command, you just need to add a Small Button or Large Button item underneath a Chunk - new or existing - to place your button on the ribbon. The “SEO” chunk in the above screenshot is an example of what you want to end up with.

The key piece of all of this is how to have your button actually load the field editor, and telling it what fields to load. You do this by configuring the Click field on the button to run the webedit:fieldeditor command like so:

webedit:fieldeditor(fields=Browser Title|Description|Keywords, command={007A0E9E-59AA-48BB-84F2-6D25A8D2EF80})

The fields argument is pretty easy to understand - a pipe delimited list of fields to edit, just like a WebEdit Custom Experience Button has (this command is in fact the one used by custom experience buttons). The command parameter I am not sure what it is used for. Internally it seems to need to be an item in the core db that exists - I used the GUID of my button item, and that worked fine.

And here’s what you end up with when you’re done, for a very small amount of work:

result

This worked for me on Sitecore 7 (RTM), but I suspect the technique would work great on earlier versions of Sitecore as well.