Force.com allows developers and administrators to control access to data at many different levels. You can control access at the object-level, the record-level, and at the field-level. This article will focus on methods for controlling access to data at the object and field levels.
After an introduction to object and field level security, this article looks at the different techniques that force.com applications can use to enforce a customer's security settings.
Object-level security within the salesforce.com environment is referred to as Create-Read-Update-Delete (CRUD) access. CRUD settings are applied at the profile level and can be used to restrict the actions that users can take on each type of standard and custom object. An example use of CRUD would be to remove the ability for a custom "auditor" profile to update, create, or delete any Account record.
Field-level security (FLS) is configured similarly to CRUD but allows administrators to define the profiles that can see and write to most fields of standard and custom objects. Example uses of FLS would be to make the Expected Revenue field of the Opportunity object invisible to all profiles outside of sales and management.
When rendering VisualForce pages, the platform will automatically enforce CRUD and FLS when the developer references SObjects and SObject fields directly in the VisualForce page. For example, if a user without FLS visibility to the Phone field of the Contact object was to view the below page, phone numbers would be automatically removed from the table.
VisualForce will also remove fields for which users do not have FLS visibility when rendering edit pages. Additionally, all apex:inputField tags will be rendered as read-only elements for fields that are set to read-only through FLS. Input tags such as apex:inputText and apex:inputTextArea will also automatically enforce FLS restrictions.
There are often cases where developers use VisualForce to display data derived from an SObject field in an indirect or processed form. For instance, a page controller may use internal logic to determine the appropriate value to display. A simple example of this would be a page that displays a random SObject Name field from a list of SObjects:
and its corresponding Apex controller:
The above example indirectly displays the Name field of the Contact object by using a customer getter method that returns a string value. Because VisualForce only sees the return value as a string and not as an SObject field, CRUD and FLS is not automatically enforced and it is necessary to call isAccessible() on the appropriate Describe Field Result in order to manually check the user's CRUD and FLS access. Please note that calling isAccessible() or any field-level access checks on a field automatically checks that the user has the corresponding CRUD access to the object type.
Apex code that updates fields or creates objects using customer setters or other internal logic also require manual CRUD/FLS checks. An example would be a page that performs a bulk update of a number of objects:
and its supporting controller extension:
A slightly more complicated example creates SObjects and also uses page messages to display access control errors to the user. In the below, a simple VisualForce page displays a lead and allows a user to create basic Account and Contact objects from its information:
Since there are multiple Contact fields on which to check access, convertLead() first obtains a map of field names and their field tokens. It then iterates over a list of fields that it has been designed to populate and checks if the user has the appropriate access. In this example, the controller aborts the operation completely but developers should consider having graceful degradation within their applications if appropriate for their design.
Delete operations occurring in custom controllers or controller extensions always need to check that the calling user has CRUD/delete access. Delete is only checked at the object level (CRUD) and not at the field level (FLS).
If you are using controller extensions and intend to delete the active record, another option is to call the standard controller's delete() function instead of deleting the object within the controller extension. The standard controller will automatically check CRUD access before performing the operation.
The field describe calls available in Apex are also available in VisualForce through the $ObjectType element. While enforcement in Apex controllers is preferred for scalability and general robustness reasons, there are situations where manual enforcement in VisualForce is useful.
Since Apex web services do not have a VisualForce binding layer, all CRUD and FLS enforcement must be done within the Apex code.