Table of Contents
Table of Contents
All tasks related to security of a FLOW3 application are handled centrally by the security framework. Besides other functionality, this includes especially features like authentication, authorization, channel security and a powerful ACL (Access Control Lists) component. This chapter describes how you can use FLOW3's security features and how they work internally.
Before you can use any of the described features in this chapter you will have to enable the security framework. This is done as follows in the Settings.yaml configuration file:
Example 13.1. Example: Enable the security features in the Settings.yaml configuration file
FLOW3: security: enable: yes
After that, the security framework engages with FLOW3 by vowing in two AOP advices into the MVC dispatcher class.
The first security advice (initializeSecurity
in the
F3\FLOW3\Security\Aspect\RequestDispatchingAspect)
initializes the security context holder for the current request. The
default implementation
(F3\FLOW3\Security\ContextHolderSession), shipped
with FLOW3, lies in session scope and holds context data like the
current authentication status. That means, if you need data related to
security, the security context (you can get it easily from the security
context holder) will be your main information source. The details of the
context's data will be described in the next chapters.
One of the main things people associate with security is authentication. That means to identify your communication partner - the one sending a request to FLOW3. Therefore the framework provides an infrastructure to easily use different mechanisms for such a plausibility proof. The most important achievment of the provided infrastructure is its flexible extensibility. You can easily write your own authentication mechanisms and configure the framework to use them without touching the framework code itself. The details are explained in the section "Implementing your own authentication mechanism".
First, let's see how you can use FLOW3's authentication features.
There is a special controller in the security package: the
AuthenticationController. This controller has two
actions, namely authenticateAction() and
logoutAction(), an appropriate route is configured.
If you call http://localhost/flow3/authenticate in
your Browser, the default authentication mechanism will be triggered.
This mechanism, implemented in a so called authentication provider,
authenticates an user account by checking an username and password
against accounts stored in the content repository. [7]
The configuration for this default provider, which is shipped with FLOW3's default configuration looks like this:
Example 13.2. Configuration of the default UsernamePassword authentication mechanism in Settings.yaml
FLOW3: security: authentication: providers: DefaultProvider: providerClass: PersistedUsernamePasswordProvider
This registers the PersistedUsernamePasswordProvider
authentication provider under the name
"DefaultProvider" as the only, global authentication
mechanism. To successfully authenticate an account with this default
provider, you'll obviously have to provide a username and password. This
is done by sending two POST variables to the authentication controller.
Have a look at the following HTML snippet with a simple login form you
can use for that:
Example 13.3. Example for a simple login form
<form action="flow3/authenticate" method="post" name="loginform"> <input type="text" id="username" name="F3\FLOW3\Security\Authentication\Token\UsernamePassword::username" value="" tabindex="1" /> <input type="password" id="password" name="F3\FLOW3\Security\Authentication\Token\UsernamePassword::password" value="" tabindex="2" /> <input type="submit" value="Login" tabindex="3" /> </form>
After submitting the form, the internal authentication process will be triggered and if you provided valid credentials an account will be authenticated afterwards[8].
At the moment the authenticate() action
does not redirect after authentication. This feature is definitely
planned and will be integrated as soon as possible.
Now that you know, how you can authenticate someone, let's have a look at the internal process, how this works internally. The following sequence diagram shows the participating components and their interaction:
As already explained, the security framework is initialized in the
dispatcher by vowing in an AOP advice, which resides in the
RequestDispatchingAspect class. This advice
intercepts the request dispatching before any controller is called.
Regarding authentication, you can see, that a so called authentication
token will be stored in the security context and some credentials will
be updated in it.
An authentication token holds the status of a specific
authentication mechanism, i.e. it stores the credentials (e.g. a
username and password) needed for authentication and one of the
following authentication states in the session. [9]The constants are defined in the authentication token
interface
(F3\FLOW3\Security\Authentication\TokenInterface)
and the status can be obtained from the
getAuthenticationStatus()method of a token.
If you only want to know, if authentication was successful,
you can call the convenient method
isAuthenticated().
NO_CREDENTIALS_GIVENThis is the default state. The token is not authenticated and holds no credentials, that could be used for authentication.
WRONG_CREDENTIALSIt was tried to authenticate the token, but the credentials were wrong.
AUTHENTICATION_SUCCESSFULThe token has been successfully authenticated.
AUTHENTICATION_NEEDEDThis indicates, that the token holds credentials, but has not been authenticated yet.
Now you might ask yourself, how the credentials are updated in a
token. The simple answer is: It's up to the token, to get them from
somewhere. The default UsernamePassword token for
example looks for a username and password in the two POST parameters:
F3\FLOW3\Security\Authentication\Token\UsernamePassword::username
and
F3\FLOW3\Security\Authentication\Token\UsernamePassword::password
(see Using the
authentication controller). The framework only makes sure that
updateCredentials() is called on every token, then
the token has to set possibly available credentials itself, e.g. from
available headers or parameters or anything else you can provide
credentials with.
After the tokens have been initialized the original request will
be processed by the resolved controller. In our case this is the
special authentication controller
(F3\FLOW3\Security\Authentication\Controller\AuthenticationController)
of FLOW3, which will call the authentication manager to authenticate
the tokens. In turn the authentication manager calls all
authentication providers in the configured order. A provider
implements a specific authentication mechanism and is therefore
responsible for a specific token type. E.g. the already mentioned
PersistedUsernamePasswordProvider provider is able to authenticate
the UsernamePassword token.
After checking the credentials, it is the responsibility of an
authentication provider to set the correct authentication status (see
above) and so called Roles in its
corresponding token. The RoleInterface
resides in the F3\FLOW3\Security\Authentication
namespace and the default implementation are Role
objects (see the ACL section).
In the previous section you have seen, how accounts can be
authenticated in FLOW3. What was concealed so far is, how these accounts
are created or what is exactly meant by the word "account". First of all
let's define what accounts are in FLOW3 and how they are used for
authentication. Following the OASIS CIQ V3.0[10] specification, an account used for authentication is
separated from an user or more general a party. The advantage of this
separation is the possibility of one user having more than one account.
E.g. an user could have an account for the
UsernamePassword provider and one account connected
to a LDAP authentication provider. Another scenario would be to have
different accounts for different parts of your FLOW3 application. Read
the next section "Advanced authentication
configuration" to see how this can be accomplished.
As explained above, the account stores the credentials needed for
authentication. Obviously these credentials are provider specific and
therefore every account is only valid for a specific authentication
provider. This provider - account connection is stored in a property of
the account object named
"authenticationProviderName". Appropriate getters and
setters are provided. The provider name is configured in the
Settings.yaml file. If you look back to the default configuration,
you'll find the name of the default authentication provider:
"DefaultProvider". Besides that, each account has
another property called "credentialsSource", which
points to the place or describes the credentials needed for this
account. This could be a LDAP query string, or in case of the
PersistedUsernamePasswordProvider provider, the username, password
hash and salt are stored directly in this member variable.
It is the responsibility of the authentication provider to check the given credentials from the authentication token[11], find the correct account for them and to decide about the authentication status of this account.
In case of a directory service, the real authentication will probably not take place in the provider itself, but the provider will pass the result of the directory service on to the authentication token.
Creating an account is as easy as creating a new account object and add it to the account repository. Look at the following example, which adds a new account for FLOW3's default username/password provider:
Example 13.4. Add a new username/password account
$account = $this->objectFactory->create('F3\Party\Domain\Model\Account'); $username = 'andi'; $password = 'secret'; $salt = 'someRandomSalt'; $credentials = md5(md5($password) . $salt) . ',' . $salt; $roles = array( $this->objectFactory->create('F3\FLOW3\Security\ACL\Role', 'Administrator'), ); $account->setAccountIdentifier($username); $account->setCredentialsSource($credentials); $account->setAuthenticationProviderName('TYPO3BEProvider'); $account->setRoles($roles); $this->accountRepository->add($account);
The way the credentials are coded is completely up to the
authentication provider. The PersistedUsernamePasswordProvider
provider expects a simple salted password hash. As account identifier
the username is used, of course. You can also see, that there is a
role object added to the account. This is used by the ACL system and
will be explained in the according section below.
This example expects the object factory and the account
repository to be in $this->objectFactory and
$this->accountRepository respectively. If you
use this snippet in an action controller, the object factory will be
there already and the account repository can be injected very easily
by dependency injection.
Now that you have seen all components, taking part in the authentication process, it is time to have a look at some advance configuration possibilities. Just to remember, here is again the configuration of the default authentication provider:
security: authentication: providers: DefaultProvider: providerClass: PersistedUsernamePasswordProvider
If you have a closer look at this configuration, you can see, that the word providers is plural. That means, you have the possibility to configure more than one provider and use them in "parallel".
You will have to make sure, that each provider has a unique
name. In the example above the provider name is
"DefaultProvider".
Example 13.5. Configuration of two authentication providers
security: authentication: providers: MyLDAPProvider: providerClass: F3\MyCoolPackage\Security\Authentication\MyLDAPProvider options: 'Some LDAP configuration options' DefaultProvider: providerClass: PersistedUsernamePasswordProvider
This will advice the authentication manager to first authenticate over the LDAP provider and if that fails he will try to authenticate the default provider. So this configuration can be seen as a authentication fallback chain, of course you can configure as many providers as you like, but keep in mind that the order matters.
As you can see in the example, the LDAP provider is provided with some options. These are specific configuration options for each provider, have a look in the detailed description to know if a specific provider needs more options to be configured and which.
There is another configuration option to realize a more-factor-authentication. This option simply forces the authentication manager to always authenticate all configured providers and to make sure that every single provider returned a positive authentication status to its token. This option is by disabled by default and can be enabled with the following configuration:
security: authentication: authenticateAllTokens: yes
Now that you know about the possibility of configuring more than one authentication provider another scenario may come to your mind. Just imagine an application with two areas: One user area and one administration area. Both must be protected, so we need some kind of authentication. However for the administration area we want a stronger authentication mechanism than for the user area. Have a look at the following provider configuration:
Example 13.6. Using request patterns
security: authentication: providers: MyLDAPProvider: providerClass: F3\MyCoolPackage\Security\Authentication\MyLDAPProvider options: 'Some LDAP configuration options' requestPatterns: controllerObjectName: F3\MyApplication\AdministrationArea\.* DefaultProvider: providerClass: PersistedUsernamePasswordProvider requestPatterns: controllerObjectName: F3\MyApplication\UserArea\.*
Look at the new configuration option
"requestPatterns". This enables or disables an
authentication provider, depending on a given pattern. The patterns
will look into the data of the current request and tell the
authentication system, if they match or not. The patterns in the
example above will match, if the controller object name of the current
request (the controller to be called) matches on the given regular
expression. If a pattern does not match, the corresponding provider
will be ignored in the whole authentication process. In the above
scenario this means, all controllers responsible for the
administration area will use the LDAP authentication provider, the
user area controllers will be authenticated by the default
username/password provider.
You can use more than one pattern in the configuration. Then the provider will only be active, if all patterns match on the current request.
There can be patterns that match on different data of the request. Just imagine an IP pattern, that matches on the request IP. You could, e.g. provide different authentication mechanisms for people coming from your internal network, than for requests coming from the outside.
You can easily implement your own pattern. Just implement the
interface
"F3\FLOW3\Security\RequestPatternInterface" and
configure the pattern with its full qualified namespace.
Table 13.1. Available request patterns
| Request Pattern | Match criteria | Configuration options |
|---|---|---|
| controllerObjectName | Matches on the object name of the controller that has been resolved by the MVC dispatcher for the current request. | Expects one regular expression, to match on the object
name. E.g.:
F3\MyApplication\AdministrationArea\.* |
One question that has not been answered so far is: what happens if
the authentication process fails? In this case the authentication
manager will throw an AuthenticationRequired
exception. It might not be the best idea to let this exception settle
its way up to the browser, right? Therefore we introduced a concept
called authentication entry points. These entry points catch the
mentioned exception and should redirect the user to a place where she
can provide proper credentials. This could be a login page for the
username/password provider or a HTTP header for HTTP authentication. An
entry point can be configured for each authentication provider. Look at
the following example, that redirects to a login page (Using the
WebRedirect entry point).
Example 13.7. Redirect an AuthenticationRequired
exception to the login page
security: authentication: providers: DefaultProvider: providerClass: PersistedUsernamePasswordProvider entryPoint: WebRedirect: uri: login/
Of course you can implement your own entry point and configure
it by using its full qualified class name. Just make sure to implement
the
"F3\FLOW3\Security\Authentication\EntryPointInterface"
interface.
It is planed to make the catching of the exception and returning back to the original request a lot more flexible by using a so called request stack. Unfortunately the MVC framework lacks of this functionality at the moment. Stay tuned for any updates on this topic.
Table 13.2. Available authentication entry points
| Entry Point | Description | Configuration options |
|---|---|---|
| WebRedirect | Triggers an HTTP redirect to a given uri. | Expects an associative array with one entry. E.g.:
uri: login/ |
This section explains the details of each authentication mechanism shipped with FLOW3. Mainly the configuration options and usage will be exposed, if you want to know more about the entire authentication process and how the components will work together, please have a look in the previous sections.
The implementation of the corresponding authentication provider
resides in the class
F3\FLOW3\Security\Authentication\Provider\PersistedUsernamePasswordProvider.
It is able to authenticate tokens of the type
F3\FLOW3\Security\Authentication\Token\UsernamePassword.
It expects a credentials array in the token which looks like
that:
array( 'username' => 'admin', 'password' => 'plaintextPassword' );
It will try to find an account in the
F3\Party\Domain\Repository\AccountRepository that
has the username value as account identifier and fetch the credentials
source, which has to be in the following format:
MD5HashOfThePassword,Salt
You should use a different, random salt for each account.
The provider will explode the credentials source by the "," and try to authenticate the token with the following comparison:
md5(md5($plaintextPasswordFromToken) . $saltFromCrendentialsSource) === $passwordHashFromCredentialsSource
If you want to know more about accounts and how you can create them, look in the corresponding section above.
The username/password token is implemented in the class
F3\FLOW3\Security\Authentication\Token\UsernamePassword.
It fetches the credentials from the HTTP POST data, look at the
following program listing for details:
$postArguments = $environment->getRawPostArguments(); $credentials['username'] = $postArguments['F3\FLOW3\Security\Authentication\Token\UsernamePassword::username']; $credentials['password'] = $postArguments['F3\FLOW3\Security\Authentication\Token\UsernamePassword::password'];
The token expects a plaintext password in the POST data. That does not mean, you have to transfer plaintext passwords, however it is not the responsibility of the authentication layer to encrypt the transfer channel. Look in the section about channel security for any details.
One of the main goals for the authentication architecture was to provide an easily extensible infrastructure. Now that the authentication process has been explained, you'll find here the steps needed to implement your own authentication mechanism:
You'll have to provide an authentication token, that implements
the interface
F3\FLOW3\Security\Authentication\TokenInterface:
The most interesting method is
updateCredentials(). There you'll get the current
request and you'll have to make sure that credentials sent from the
client will be fetched and stored in the token.
Implement the remaining methods of the interface. These are
mostly getters and setters, have a look in one of the existing
tokens (e.g.
F3\FLOW3\Security\Authentication\Token\UsernamePassword),
if you need more information.
After that you'll have to implement your own authentication
strategy by providing a class, that implements the interface
F3\FLOW3\Security\Authentication\AuthenticationProviderInterface:
In the constructor you will get the name, that has been configured for the provider and an optional options array. Basically you can decide on your own which options you need and how the corresponding yaml configuration will look like.
Then there has to be a canAuthenticate()
method, which gets an authentication token and returns a boolean
value whether your provider can authenticate that token or not. Most
likely you will call
getAuthenticationProviderName() on the token and
check, if it matches the provider name given to you in your
provider's constructor. In addition to this, the method
getTokenClassNames() has to return an array with
all authentication token classes, your provider is able to
authenticate.
All the magic will happen in the
authenticate() method, which will get an
appropriate authentication token. Basically you could do whatever
you want in this method, the only thing you'll have to make sure is
to set the correct status (possible values are defined as constants
in the token interface and explained above). If authentication
succeeds you might also want to set an account in the given token,
to add some roles to the current security context.
However, here is the recommended way of what should be done in this
method and if you don't have really good reasons, you shouldn't
deviate from this procedure.
Get the credentials provided by the client from the
authentication token
(getCredentials())
Retrieve the corresponding account object from the account
repository, which you should inject into your provider by
dependency injection. The repository provides a convenient find
method for this task:
findByAccountIdentifierAndAuthenticationProviderName().
The credentialsSource property of the
account will hold the credentials you'll need to compare or at
least the information, where these credentials lie.
Start the authentication process (e.g. compare credentials/call directory service/...).
Depending on the authentication result, set the correct
status in the authentication token, by calling
setAuthenticationStatus().
Set the account in the authentication token, if authentication succeeded. This will add the roles of this token to the security context.
In this section we will deal with the authorization features of FLOW3. You won't find any advices, how to configure access rights here, please refer to the next section about access control lists, which form the default method to model and configure access rules.
The most general thing, which you want to protect in every application is the invocation of certain methods. By controlling, which methods are allowed to be called and which not, it can be globally ensured, that no unprivileged action will be executed at any time. This is what you would usually do, by adding an access check at the beginning of your privileged method. In FLOW3, there is the opportunity to enforce these checks without touching the actual method at all. Of course FLOW3's AOP features are used to realize this completely new perspective on authorization. If you want to learn more about AOP, please refer to the corresponding chapter in this reference.
First, let's have a look at the following sequence diagram to get an overview of what is happening when an authorization decision is formed and enforced:
As already said, the whole authorization starts with an
intercepted method, or in other words with a method that should be
protected and only be called by privileged users. In the chapter about
AOP you've already read, that every method interception is implemented
in a so called advice, which resides in an aspect class. Here we are:
the F3\FLOW3\Security\Aspect\PolicyEnforcementAspect.
Inside this aspect there is the enforcePolicy()
advice, which hands over to FLOW3's authorization components.
The next thing to be called is a security interceptor. This
interceptor calls the authentication manager before it continues with
the authorization process, to make sure that the authentication status
is up to date. Then an access decision manager is called, which has to
decide, if it is allowed to call the intercepted method. If not it
throws an access denied exception. If you want, you could implement your
own access decision manager. However, there is a very flexible one
shipped with FLOW3
(F3\FLOW3\Security\Authorization\AccessDecisionVoterManager),
which uses the following voting process to meet its decision:
Check for registered access decision voters.
Ask every voter, to vote for the given method call.
Count the votes and grant access, if there is at least one
"VOTE_GRANT" vote and no
"VOTE_DENY" vote. In all other cases an access
denied exception will be thrown.
As you have seen, the default way of deciding on access is done by
voting. This makes the whole authorization process very flexible and
very easily extensible. You can at any time write your own voter classes
and register them, just make sure to implement the interface
F3\FLOW3\Security\Authorization\AccessDecisionVoterInterface.
Then you have to register your custom voter as shown
below:
security: authorization: accessDecisionVoters: [F3\FLOW3\Security\Authorization\Voter\Acl, F3\MyPackage\Security\MyCustomVoter]
By default there is always one voter registered:
F3\FLOW3\Security\Authorization\Voter\Acl. This
voter connect the authorization system to the ACL component, by
return a vote depending on the configured security policy. Read the
section about ACLs, to learn more about the default policy handling
in FLOW3.
If asked, each voter has to return one of the three possibles votes: grant, deny or abstain. There are appropriate constants defined in the voter interface, which you should use for that. You might imagine that a voter has to return an abstain vote, if it is not able to give a proper grant or deny vote.
Now it could be the case that all registered voters abstain. Usually the access decision manager will deny access then. However, you can change set by configuring the following option:
security: authorization: allowAccessIfAllVotersAbstain: FALSE
Besides the AOP powered authorization, there is another line of defense: the filter firewall. This firewall is triggered directly when a request arrives at the MVC dispatcher. After that the request is analyzed and can be blocked/filtered out. This adds a second level of security right at the beginning of the whole framework run, which means that a minimal amount of potentially insecure code will be executed before that.
The firewall itself is added to the MVC dispatcher by AOP, to completely decouple security from the MVC framework and to have the possibility of disabling security. Blocking requests with the firewall is not a big thing at all, basically a request filter object is called, which consists of a request pattern and a security interceptor. The simple rules is: if the pattern matches on the request, the interceptor is invoked. Request patterns are also used by the authentication components and are explained in detail there. Talking about security interceptors: you already know the policy enforcement interceptor, which triggers the authorization process. Here is a table of available interceptors, shipped with FLOW3:
Of course you can implement your own interceptor. Just make sure
to implement the interface:
F3\FLOW3\Security\Authorization\InterceptorInterface.
Table 13.3. FLOW3's built-in security interceptors
| Security interceptor | Invocation action |
|---|---|
| PolicyEnforcement | Triggers the authorization process as described one section above. |
| RequireAuthentication | Calls the authentication manager to authenticate all active tokens for the current request. |
Of course you are able to configure as many requests filters as you like. Have a look at the following example to get an idea how a firewall configuration will look like:
Example 13.8. Example firewall configuration in the Settings.yaml file
FLOW3: security: firewall: rejectAll: n filters: - patternType: URL patternValue: /some/url/.* interceptor: AccessGrant - patternType: URL patternValue: /some/url/blocked.* interceptor: AccessDeny - patternType: F3\MyPackage\Security\MyOwnRequestPattern patternValue: some pattern value interceptor: F3\MyPackage\Security\MyOwnSecurityInterceptor
As you can see, you can easily use your own implementations for request patterns and security interceptors.
You might have noticed the rejectAll
option. If this is set to yes, only request which
are explicitly allowed by a request filter will be able to pass the
firewall.
The current implementation of the ACL system is very basic. However, the concept for this component is ready for implementation and there'll be soon much more powerful declarative authorization possibilities than now. So please stay tuned for any updates on this issue.
This section will introduce the recommended and default way of connection authentication with authorization. The special and really powerful part of FLOW3's way is the possibility to do that completely declarative. This gives you the possibility to change the security policy of your application, without touching any PHP code. The ACL system deals with three major objects, which are explained below: roles, resources and acl entries.
In the section about authentication so called roles
were introduced. A role can be attached to an users security
context, to determine which rights should be granted to her. I.e. the
access rights of a user are decoupled from the user object itself, making
it a lot more flexible, if you want to change them. Another word for
role is role. In FLOW3 a role or role is mainly
just a string, which must be unique in the whole FLOW3 instance. Following
there is an example configuration, that will proclaim the roles
Administrator, Customer, and
PrivilegedCustomer to the system.
Example 13.9. Example roles definition in the Settings.yaml file
FLOW3: security: policy: roles: Administrator: [] Customer: [] PrivilegedCustomer: [Customer]
The role PrivilegedCustomer is configured as
a sub role of Customer, i.e. it will inherit the
access rights for the Customer role.
The counterpart to roles are resources. A resource in general is an object, you want to protect, i.e. you want to configure which roles are allowed to access a certain resource. The policy configuration deals only with method resources, access to other resources like content will be handled by the content repository.
Example 13.10. Example resources definition in the Settings.yaml file
FLOW3: security: policy: resources: update: "method(F3\FooPackage\SomeClass->update.*())" delete: "method(F3\FooPackage\.*->delete.*())" modify: "update || delete"
Each resource is defined by a unique name and so called pointcut expression. Practically a pointcut expression is a regular expression that matches on certain methods. There are more pointcut expressions you can use to describe the methods addressed by a specific resource, the whole syntax is described in detail in the chapter about AOP.
To make your resource definitions better readable you can cascade them by connecting two or more via logical operators. In the above example this is shown in the configuration of the third resource. Again the details about combined pointcuts are described in the AOP reference.
The last step is to connect resources with roles by assigning access privileges. Let's have a look at an example for such ACL entries:
Example 13.11. Example for ACL entry definitions in the Settings.yaml file
FLOW3: security: policy: acls: Administrator: modify: ACCESS_GRANT Customer: modify: ACCESS_DENY PrivilegedCustomer: update: ACCESS_GRANT delete: ACCESS_DENY
This will end up in Administrators being
able to call all update* methods in the class
SomeClass and all delete* methods no
matter which class in the whole package FooPackage.
However, Customers won't be able to call them and
PrivilegedCustomers are only allowed to call the
update* methods. And all this without touching one line
of PHP code, isn't that convenient?
Now that the policy is technically enforced, these rules should
also be reflected in the view. E.g. a button or link to delete a
customer should not be shown, if the user has not the privilege to do
so. If you are using the recommended Fluid templating engine, you can
simply use the security view helpers shipped with Fluid. Otherwise you
would have to ask the policy service
(F3\FLOW3\Security\ACL\PolicyService) for the current
privilege situation and implement the view logic on your own, however
this seems not to be the best idea one can have. Below you'll find a
short description of the available Fluid view helpers.
ifAccess view helperThis view helper implements an ifAccess/else condition, have a look at the following example, which should be more or less self-explanatory:
Example 13.12. Example for the ifAccess view
helper
<f:security.ifAccess resource="someResource"> This is being shown in case you have access to the given resource </f:security.ifAccess> <f:security.ifAccess resource="someResource"> <f:then> This is being shown in case you have access. </f:then> <f:else> This is being displayed in case you do not have access. </f:else> </f:security.ifAccess>
As you can imagine, the main advantage is, that the view will automatically reflect the configured policy rules, without the need of changing any template code.
ifHasRole view helperThis view helper is pretty similar to the
ifAccess view helper, however it does not check the
access privilege for a given resource, but the availability of a
certain role. E.g. you could check, if the current user
has the Administrator role assigned:
Example 13.13. Example for the ifHasRole view
helper
<f:security.ifHasRole role="Administrator"> This is being shown in case you have the Administrator role (aka role). </f:security.ifHasRole> <f:security.ifHasRole role="Administrator"> <f:then> This is being shown in case you have the role. </f:then> <f:else> This is being displayed in case you do not have the role. </f:else> </f:security.ifHasRole>
[7] The details about the PersistedUsernamePasswordProvider
provider are explained below, in the section about FLOW3's
built in providers.
[8] If you don't know any credentials, you'll have to read the section about account management.
[9] Well, it holds them in member variables, but lies itself in the security context, which lies in the security context holder, which is a class configured as scope session.
[10] The specification can be downloaded from http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=ciq.
The implementation of this specification resides in the "Party"
package, which is part of the official FLOW3 distribution.
[11] The AccountRepository provides a convenient
find method called
findByAccountIdentifierAndAuthenticationProviderName()
for this task.