Hanynowsky
Hanynowsky

Reputation: 3010

How to properly use isUserInRole(role)

To prevent a user role from performing an action.

  1. Example 1: The role "administrator" is the only role allowed to perform destroy action.
  2. Example 2: Any role different from "guest" can perform CREATE action.

In a real case, I have this:

public String delete() {
 if(FacesContext.getCurrentInstance().getExternalContext().isUserInRole("administrator"){
   //.....the action to perform
 }
 return "Denied";
}

I wish I could use the annotation @RolesAllowed() of EJB yet I am not using EJB but ManagedBeans. So the question is: Is there any way to use many roles at the same time? Some workaround! Example: If an action must be allowed to 3 roles (administrator, moderator, manager). I am obliged to do :

if (FacesContext.getCurrentInstance().getExternalContext().isUserInRole("administrator")
    || FacesContext.getCurrentInstance().getExternalContext().isUserInRole("manager") 
    || .....) {
  //....
}

And it is a pain to reproduce on all the methods. Something like hundreds of methods :(

Upvotes: 15

Views: 26161

Answers (3)

BalusC
BalusC

Reputation: 1108912

This needs to be controlled in the view side. Don't you find it by yourself very annoying when you see on some site a button for which you don't have sufficient rights to press and thus get an intimidating error page when you do so?

Just render the button in the view side only when the user has the required role, else hide it altogether.

<h:commandButton value="Delete" action="#{bean.delete}" 
    rendered="#{request.isUserInRole('administrator')}" />

This is not sensitive to (CSRF) hacks as JSF checks the condition once again during apply request values phase.

As to using multiple conditions and repeating the same over and over in a single view, consider using <c:set> to give it a short alias. You could even place it in the top of some master template so that it's available to all child templates.

<c:set var="isPowerUser" value="#{request.isUserInRole('manager') or request.isUserInRole('administrator')}" scope="request" />
...
<h:commandButton rendered="#{isPowerUser}" />
...
<h:commandButton rendered="#{isPowerUser}" />

Upvotes: 32

ag112
ag112

Reputation: 5687

@Mediterran81: So basically you are looking for bean-method based authorization solution...how are you instantiating your managed beans? You may like to introduce a simple XML format:-

<bean class="">
 <method name="">
  <role> xyz</role>
 </method>
</bean>

Have this XML read by utility class and then only thing you would need to do is to call Utility's static method to determine if method is allowed to execute.

Upvotes: 1

Bozho
Bozho

Reputation: 597134

You can shorten that by moving the logic to an utility method:

public class AuthorizationUtils {
    public static boolean isUserInRoles(String[] roles) {
        for (String role : roles) {
            if (FacesContext........isUserInRole(role)) {
                return true;
            }
        }

        return false;
    }
}

And then invoke it with:

if (AuthorizationUtils.isUserInRoles(new String[] {"administrator", "moderator"})) {
    ..
}

If you are using CDI, you can make an interceptor that handles the @RolesAllowed annotation

Upvotes: 7

Related Questions