How prevent a model data save using _save_before event

If you have a look at the method Mage_Core_Model_Abstract::save, you see this code block:

try {
    $this->_beforeSave();
    if ($this->_dataSaveAllowed) {
        $this->_getResource()->save($this);
        $this->_afterSave();
    }
    $this->_getResource()->addCommitCallback(array($this, 'afterCommitCallback'))
        ->commit();
    $this->_hasDataChanges = false;
    $dataCommited = true;
} catch (Exception $e) {
    $this->_getResource()->rollBack();
    $this->_hasDataChanges = true;
    throw $e;
}

In the _beforeSave() method in the second line, the save_before event is dispatched. Hence, you should be able to just throw an exception in your observer code. This should be catched by the try-catch-block above and should prevent the model to save.

Another possibility is the _dataSaveAllowed field. You can set it to false in your observer code. This will prevent the model to save. And this field is exactly designed for this purpose as the PHP doc reveals:

/**
 * Flag which can stop data saving after before save
 * Can be used for next sequence: we check data in _beforeSave, if data are
 * not valid - we can set this flag to false value and save process will be stopped
 *
 * @var bool
 */
protected $_dataSaveAllowed = true;

In case you need to prevent the save method to execute for a core model (i.e. Catalog/Product), you can use reflection to set "$_dataSaveAllowed" to false:

public function catalogProductSaveBefore($observer)
{
    try {
        $product = $observer->getProduct();

        $reflectionClass = new ReflectionClass('Mage_Catalog_Model_Product');
        $reflectionProperty = $reflectionClass->getProperty('_dataSaveAllowed');
        $reflectionProperty->setAccessible(true);
        $reflectionProperty->setValue($product, false);
    } catch (Exception $e) {
            Mage::log($e->getMessage());
    }

    return $this;
}