Visualforce pages exposing the SObject information (either via Standard, Custom, or Extension Controllers) can leverage built-in field-level security enforcements when using components or expressions that reference SObject fields directly; such usage will honor the user's field-level security. However, Visualforce expressions referencing SObject fields by way of a controller property are not affected, as the Visualforce engine cannot tell whether the controller property in turn refers to an SObject field.
Lightning does not currently offer components that are sensitive to object- and Field-Level security. You must, instead, inform the client side controller of the permissions via a Lightning server-side action that leverages Apex Describe for the information being accessed. The Lightning Data Service component, in Developer Preview at time of writing, does, however, support not only object and field security, but also sharing rules. Developer Preview status means it is not possible to package components using it.
When using the Visualforce apex:inputField
and apex:outputField
components, fields (including the label if present) will be hidden or made read only accordingly. A less well-known fact is that direct SObject field expressions are also affected by field-level security; for example, {!Race__c.Status__c}
will not be evaluated (no output emitted to the page) if the user has no read access to the Status__c
field. This behavior is particularly subtle and not well documented.
The documentation states that when using components such as apex:inputText
and apex:ouputText
, these will not enforce field security. While this is correct, security is always applied to SObject field expressions as well. So, if a field is not visible (as opposed to just read only), even the apex:outputText
component will not display a value. However, if a field is read only and is used with apex:inputText
(for example), it will render as an editable field. Thus, the general guideline here is that, if you have an SObject field expression, use the recommended apex:inputField
and apex:outputField
components.
A common confusion point is the use of the with sharing
and without sharing
keywords on the associated controllers. These keywords have no effect at all on the enforcement of field-level security; they purely determine record visibility, and thus effect only SOQL queries made within the controller and other Apex classes that make SOQL queries that are called by this controller.
In addition to using Apex described within your controller code, you can also determine directly a field's accessibility, using the $ObjectType
global variable. For example, you can use the following expression to hide an entire section based on a given field's security, {!$ObjectType.Race__c.fields.Status__c.Accessible}
.
The following Visualforce page and associated custom controller illustrates field-level security. In the use case shown here, two users are used, one has full access and the other has been given the following permissions via their profile:
Status__c
fieldFastestLapBy__c
fieldFirst, review the Visualforce page; each section shows the following use case:
apex:inputField
apex:outputField
apex:inputText
apex:outputText
To make it easier to compare, messages are shown on the page to confirm the level of field access. The FLSDemoController
is included in the sample code for this chapter; it simply reads the first Race__c
record in your org. It exposes two string properties indirectly exposing the Status__c
and FastestLapBy__c
field values. The following shows the Visualforce page used to illustrate the effects of using different Visualforce bindings and components against the permissions of the current user:
<apex:page controller="FLSDemoController" tabStyle="Race__c"> <apex:form> <apex:pageMessage summary="Race__c.Status__c Accessible is{!$ObjectType.Race__c.fields.Status__c.Accessible}" severity="info"/> <apex:pageMessage summary="Race__c.Status__c Updatable is{!$ObjectType.Race__c.fields.Status__c.Updateable}"severity="info"/> <apex:pageMessagesummary="Race__c.FastestLapBy__c Accessible is {!$ObjectType.Race__c.fields.FastestLapBy__c.Accessible}"severity="info"/> <apex:pageMessage summary="Race__c.FastestLapBy__c Updatable is {!$ObjectType.Race__c.fields.FastestLapBy__c.Updateable}"severity="info"/> <apex:pageBlock> <apex:pageBlockSection title="Use Case A: Using apex:inputField"> <apex:inputField value="{!Race.Status__c}"/> <apex:inputField value="{!Race.FastestLapBy__c}"/> </apex:pageBlockSection> <apex:pageBlockSection title="Use Case B: Using apex:outputField"> <apex:outputField value="{!Race.Status__c}"/> <apex:outputField value="{!Race.FastestLapBy__c}"/> </apex:pageBlockSection> <apex:pageBlockSection title="Use Case C: Using apex:inputText"> <apex:inputText value="{!Race.Status__c}"/> <apex:inputText value="{!Race.FastestLapBy__c}"/> </apex:pageBlockSection> <apex:pageBlockSection title="Use Case D: Using apex:outputText"> <apex:outputText value="{!Race.Status__c}"/> <apex:outputText value="{!Race.FastestLapBy__c}"/> </apex:pageBlockSection> <apex:pageBlockSection title="Use Case E: Using SObject Field Expressions"> <apex:pageBlockSection> The value of Status__c is '{!Race.Status__c}' </apex:pageBlockSection> <apex:pageBlockSection> The value of FastestLapBy__c is'{!Race.FastestLapBy__c}' </apex:pageBlockSection> </apex:pageBlockSection> <apex:pageBlockSection title="Use Case F: Using Controller Property Expressions"> <apex:pageBlockSection> The value of Status__c is '{!Status}' </apex:pageBlockSection> <apex:pageBlockSection> The value of FastestLapBy__c is '{!FastestLapBy}' </apex:pageBlockSection> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>
For a user with full access, this page displays as follows:
The following screenshot and explanations confirm how the page reacts and displays to a user with limited access; this page shows that some information is hidden or read-only as expected, but not all, the exceptions being use Case C and Case F:
apex:inputText
field, it does not honor the field-level security status of the field and the field is editable when it should not be.FastedLapBy__c
field value is shown because it is not using a SObject field binding; it is using a binding to controller property, which is indirectly exposing the field value. In this case, the responsibility lies with the developer to check the field-level security in the controller code.18.226.177.85