аргументы для hasPermission в универсальном контроллере

Я пытаюсь реализовать общий класс контроллера, где каждый метод имеет структуру, подобную этой:

@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());
}

У меня проблемы с аннотацией PreAuthorize. имя разрешения имеет следующую структуру: _. прямо сейчас я получаю ошибку 403, когда пытаюсь получить доступ к представлению, отображаемому методом. Я также пробовал другие варианты, такие как:

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

or

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

но с тем же результатом. Кто-нибудь знает правильный способ сделать это?

ОБНОВЛЕНИЕ

Я пытаюсь вызвать эту функцию внутри методов из контроллера, защищенного этим тегом 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);
}

и когда я запускаю приложение и открываю представление, оно должно быть отображено методом из контроллера, например:

@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());
}

На консоли не отображается сообщение. Итак, я думаю, что мое приложение каким-то образом не вызывает методы из моего универсального контроллера. Я прав? Если да, то как мне это исправить?

Мои производные контроллеры следуют этой структуре:

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

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

}

person Kleber Mota    schedule 12.06.2014    source источник
comment
Я правильно понимаю, что разрешение должно иметь форму [имя_метода]_[полное_имя_класса]? Не могли бы вы добавить свою конфигурацию Spring Security, связанную с контролем доступа?   -  person pgiecek    schedule 14.06.2014
comment
Да, это формат разрешения. Конфигурация безопасности spring такова: github .com/klebermo/blog.cms/tree/master/src/main/java/com/   -  person Kleber Mota    schedule 14.06.2014


Ответы (2)


Таким образом, у вас возникли трудности с динамическим построением имени разрешения в виде [имя_метода]_[полное_имя_класса] в выражении SpEL.

Посмотрите, что документация SpEL говорит об #этой переменной ниже

Переменная #this всегда определена и ссылается на текущий объект оценки (на который разрешаются неквалифицированные ссылки).

Основываясь на документации и немного покопавшись в коде, фактический объект, который представляет #this, должен быть в вашем случае экземпляром класса org.springframework.security.access.expression.method.MethodSecurityExpressionRoot. Класс содержит несколько полезных методов, в том числе метод getThis(), который возвращает целевой объект, для которого вызывается защищенный метод (метод с аннотацией @PreAuthorize).

Вооружившись этими знаниями, не составит большого труда построить требуемое выражение. В случае метода с названием «кадастр» он должен быть следующим.

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

Надеюсь, он также будет корректно работать с защищенными методами, унаследованными от базового класса.

person pgiecek    schedule 14.06.2014

Итак, я решил эту проблему с помощью этого подхода:

1) Добавление нового метода в мой универсальный контроллер, где я возвращаю имя класса:

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) Внутри аннотации я использую возвращаемое этим методом значение и объединяю результат с константной строкой (используя нотацию, описанную пользователем @pgjecek в этой теме):

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

и теперь он работает отлично.

person Kleber Mota    schedule 15.06.2014