2

UPDATE (17.04.2012): So what I have as result.

root-context.xml:

<context:annotation-config/>
<context:component-scan base-package="com.grsnet.qvs.controller.web"/>  
<security:global-method-security pre-post-annotations="enabled" />
<bean id="permissionManager" class="com.grsnet.qvs.auth.PermissionManager"/>

PermissionManager.java

package com.grsnet.qvs.auth;

import com.grsnet.qvs.model.Benutzer;

public class PermissionManager {

public PermissionManager() {}

public boolean hasPermissionU01(Object principal, Integer permissionLevel) {
    return ((Benutzer)principal).getPermission().getU_01() >= permissionLevel;
}
}

Controller:

@PreAuthorize("@permissionManager.hasPermissionU01(principal, 1)")
@RequestMapping(value = "/u01", method = RequestMethod.GET)
public String listU01(HttpServletRequest request, Map<String, Object> map) throws Exception {
    setGridFilters(map);
    return "u01panel";      
}

I set break point in PermissionManager.hasPermissionU01. it seems my security annotation just ignored.

What is the reason? Where is my mistake?

Thanks.

END OF UPDATE

After hours of googling I have to ask here. I have

  1. Spring MVC app
  2. CustomUserDetailService
  3. Custom UserDetails class

    public class Benutzer extends User implements UserDetails {
    ...
      private Permission permission = null;
    ...
    }
    
  4. Permissions class, not very good realized, but I have to use it.

    public class Permission {
    ... 
      private Integer u_01 = 0;
    ...
    }
    
  5. Controller

    @Controller 
    public class U01Controller {
    
        @RequestMapping(value = "/u01", method = RequestMethod.GET)
        public String listU01(HttpServletRequest request, Map<String, Object> map) throws Exception {
    

My task is to secure the controller at whole and to secure a methods inside. I would like to write some like this:

@PreAuthorize("principal.permission.u_01>0")
public class U01Controller {

and

@RequestMapping(value = "/u01", method = RequestMethod.GET)
@PreAuthorize("principal.permission.u_01=2")
public String listU01(HttpServletRequest request, Map<String, Object> map) throws Exception {

It seems ACL uses UserDetails interface to gain access to a principal. Is it probably to make some type cast inside ACL?

@PreAuthorize("(com.grsnet.qvs.model.Benutzer)principal.permission.u_01=2")

Thanks in advance.

mad
  • 1,029
  • 3
  • 17
  • 38

2 Answers2

5

While I think you can probably do that (did you just try it?) it seems to me that the best approach would be to create another class that knows how to do permissions decisions. In particular, it could be done like this:

public class Decision {
    private Decision() {} // no instance, please

    // Type is probably a bit too wide...
    static boolean mayList(Object principal) {
        return ((com.grsnet.qvs.model.Benutzer)principal).permission.u_01 == 2;
    }

    // etc...
}

Then your @PreAuthorize can be written like this:

@PreAuthorize("Decision.mayList(principal)")

If the decision process was more complex, then you'd be getting into using a bean to do the decision making. Then, because this is Spring EL, you'd write (assuming you're delegating to to the decider bean):

@PreAuthorize("@decider.mayList(principal)")

(Of course, my little Decider class above definitely isn't a bean…)

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • Yeah, interesting... Could I write some like @PreAuthorize("Decision.mayList(principal) > 1") ? Thanks. – mad Apr 17 '12 at 05:43
  • Of course you _could_, but I'd go for having multiple methods — one per decision — where each returns a boolean. That is, the entire decision would be in the method. I'd be willing to bet that in a non-trivial system you'd be reusing at least some of the decisions across business methods, and getting them correct in one place (and “obviously” correct everywhere else) is very valuable to maintainability. – Donal Fellows Apr 17 '12 at 05:55
  • ok, I see now. I will try later and will accept your answer or will ask you addititonally. Thanks. – mad Apr 17 '12 at 06:27
  • please look at update of basic ticket. I still having problems. – mad Apr 17 '12 at 18:21
1

prolem was solved with Donal's solution. My error was I placed

<security:global-method-security pre-post-annotations="enabled" />

in root-context.

Be careful with it and place it in servletContext.

Donal, thanks again.

mad
  • 1,029
  • 3
  • 17
  • 38