Search code examples
javaspringspring-securityspring-el

arguments for hasPermission in a generic controller


I am trying implement a generic controller class where each method has a structure similar to this:

@RequestMapping(value="cadastra")
@PreAuthorize("hasPermission(#user, 'cadastra_#this.class.name')")
public ModelAndView cadastra() throws InstantiationException, IllegalAccessException {
    return new ModelAndView("privado/"+this.entity.getClass().getName()+"/cadastra", "command", this.entity.getClass().newInstance());
}

I am having trouble with the annotation PreAuthorize. the name for the permissionhave this structure: _. right now, I am getting a 403 Error when I try access the view mapped by the method. I also tried other variations like:

@PreAuthorize("hasPermission(#user, 'cadastra_'+#this.class.name)")

or

@PreAuthorize("hasPermission(#user, 'cadastra_#this.getClass().getName()')")

but with the same result. Anyone knows the right way to accomplish this?

UPDATE

I try call this function inside the methods from controller secured by this tag PreAuthorize:

private void expressionParser() {
    System.out.println("expressionHandler()");
    ExpressionParser parser = new SpelExpressionParser();
    Expression expression = parser.parseExpression("'cadastra_'+#this.class.name");
    String message = (String) expression.getValue();
    System.out.println("Message is " + message);
}

and when I run the application and open the view should be mapped by a method from controller, like this one:

@RequestMapping(value="cadastra")
@PreAuthorize("hasPermission(#user, 'cadastra_'+#this.class.name)")
public ModelAndView cadastra() throws InstantiationException, IllegalAccessException {
    this.expressionParser();
    return new ModelAndView("privado/"+this.entityClass.getName()+"/cadastra", "command", this.entityClass.newInstance());
}

No message is displayed on the console. So, I am thinking my application somehow aren't calling the methods from my generic controller. Am I right? If so, how I fix this?

My derived controllers follow this structure:

@Controller
@RequestMapping(value="usuario")
public class UsuarioController extends controller<Usuario> {

    public UsuarioController() {
        super(Usuario.class);
    }

}

Solution

  • So, I solved this issue with this approach:

    1) Adding a new method to my generic controller, where I return the name of the class:

    public String getName() {
        String expressao = entityClass.getName();
        String nome_classe = new String();
        StringTokenizer st = new StringTokenizer(expressao, ".");
        while (st.hasMoreTokens()) {
            nome_classe = st.nextToken();
        }
        return nome_classe;
    }
    

    2) Inside the annotation, I use the returned value by this method and concatenate the result with the constant string (using the notation described by the user @pgjecek in this topic):

    @PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.name)")
    

    and now it1s working perfectly.