In some situations Togglz requires knowledge about the current user that is acting in the application. The two most important reasons for this are:
The strategy to obtain the current user is represented by the UserProvider
interface. You can choose
which strategy is used by implementing TogglzConfig.getUserProvider()
like
described in Configuration.
Togglz ships with a number of default implementations for integrating with different user management scenarios.
The following section will describe each of them in detail.
This class is especially useful if your application is integrated with the authentication facilities of your container. It uses HttpServletRequest.getUserPrincipal()
for obtaining the name of the current user and HttpServletRequest.isUserInRole()
to check if the user is allowed to configure feature state using the admin console. You can optionally choose which role a user must have by specifying the group name in the constructor.
The following implementation of TogglzConfig
for an example:
public class MyTogglzConfiguration implements TogglzConfig { /* ..... */ @Override public UserProvider getUserProvider() { return new ServletUserProvider("ADMIN_ROLE"); } }
This provider implementation offers a very simple way to integrate Togglz with Seam Security. This provider can be used after adding the following dependency to your project:
<dependency> <groupId>org.togglz</groupId> <artifactId>togglz-seam-security</artifactId> <version>3.1.2</version> </dependency>
To use this provider, register it in your TogglzConfig
like this:
public class MyTogglzConfiguration implements TogglzConfig { /* ..... */ @Override public UserProvider getUserProvider() { return new SeamSecurityUserProvider(); } }
Now implement an authorizer method for @FeatureAdmin
like this:
public class SeamSecurityAuthorizer { @Secures @FeatureAdmin public boolean isFeatureAdmin(Identity identity) { // return true if the current user is allowed to toggle features } }
This provider offers integration with the Apache DeltaSpike Identity API. To use this provider, add the following dependency to your project:
<dependency> <groupId>org.togglz</groupId> <artifactId>togglz-deltaspike</artifactId> <version>3.1.2</version> </dependency>
Then change your TogglzConfig
implementation to use the provider:
public class MyTogglzConfiguration implements TogglzConfig { /* ..... */ @Override public UserProvider getUserProvider() { return new DeltaSpikeUserProvider(); } }
Please note that the provider currently doesn't support to set the feature admin flag for a user. This is because the DeltaSpike
API for authorization isn't stable yet. So if you want to set the flag using some custom criterion, you can extend
DeltaSpikeUserProvider
and overwrite the isFeatureAdmin(Identity)
method.
This implementation provides a way to integrate Togglz with Spring Security. To use this provider you have to add the following dependency to your project.
<dependency> <groupId>org.togglz</groupId> <artifactId>togglz-spring-security</artifactId> <version>3.1.2</version> </dependency>
To configure Togglz to use this provider, add it to your TogglzConfig
. Please note that you have to specify an authority name in the constructor of the class. Users with this authority will automatically be able to perform Togglz administration tasks.
public class MyTogglzConfiguration implements TogglzConfig { /* ..... */ @Override public UserProvider getUserProvider() { return new SpringSecurityUserProvider("ADMIN_AUTHORITY"); } }
Many applications are using servlet filters to implement authentication. In these scenarios authentication is typically done for a single request received by the application. If you are using such a pattern for user authentication you can use ThreadLocalUserProvider
to tell Togglz about the current user.
This implementation allows to store the current user in a ThreadLocal object for the current request. The only thing you have to do is to set the current user from your filter like this:
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String username = ...; boolean isAdmin = ...; FeatureUser user = new SimpleFeatureUser(username, isAdmin); ThreadLocalUserProvider.bind(user); try { chain.doFilter(request, response); } finally { ThreadLocalUserProvider.release(); } }
Then register the ThreadLocalUserProvider
in your TogglzConfig
like this:
public class MyTogglzConfiguration implements TogglzConfig { /* ..... */ @Override public UserProvider getUserProvider() { return new ThreadLocalUserProvider(); } }
If none of the default implementations fits you needs, you can always think about implementing a provider yourself. This is very easy.
You just have to implement a single method called getCurrentUser()
.
The following example shows an implementation which reads the username from a servlet request attribute:
public class MyTogglzConfiguration implements TogglzConfig { /* ..... */ @Override public UserProvider getUserProvider() { return new UserProvider() { @Override public FeatureUser getCurrentUser() { HttpServletRequest request = HttpServletRequestHolder.get(); String username = (String) request.getAttribute("username"); boolean isAdmin = "admin".equals(username); return new SimpleFeatureUser(username, isAdmin); } }; } }
Please note the HttpServletRequestHolder
class which may be very useful if you are implementing a UserProvider
yourself because it allows to obtain the HttpServletRequest
from anywhere in your application.