Может ли Spring оценить все символы/выражения в выражениях SpEL, когда они вводятся из файла свойств?

Интересно, почему Spring не оценивает все выражения напрямую, поскольку они вводятся из файла свойств в аннотацию @PreAuthorize(...). Я думаю, что Spring не оценивает некоторые символы, такие как '(', ')', ''' и т. д., или добавляет специальные символы поверх этих введенных значений из файла свойств. Для пояснения рассмотрим следующий пример.

@PreAuthorize("hasRole('ROLE_ADMIN')")

Приведенное выше выражение является нормальным и работает нормально. Предположим, что значения файла свойств следующие.

role1=ROLE_ADMIN
role2='ROLE_ADMIN'
role3=hasRole('ROLE_ADMIN')
  1. Давайте введем role1 из файла свойств и передадим его в @PreAuthorize("hasRole(${role1})"), все работает нормально. При обычном способе вычисления выражения hasRole(...) имя роли должно быть заключено в одинарные кавычки, т. е. 'ROLE_ADMIN'. Но здесь это работает с ROLE_ADMIN. Удивительно!.

  2. Если мы вставим role2 из файла свойств в @PreAuthorize("hasRole(${role2})"), он вернет отказ в доступе. Это означает, что оно оценивается, но мы можем понять, что значение, переданное выражению, отличается от «'ROLE_ADMIN'». Таким образом, если имя роли заключено в одинарные кавычки, доступ будет запрещен. Еще один сюрприз!.

  3. Если мы попытаемся внедрить role3 из файла свойств в @PreAuthorize("${role3}"), он также не будет оцениваться. исключения:

    • java.lang.IllegalArgumentException: Failed to evaluate expression 'role3' with root causes:
    • org.springframework.expression.spel.SpelEvaluationException: EL1001E:(pos 0): Type conversion problem, cannot convert from java.lang.String to java.lang.Boolean
    • java.lang.IllegalArgumentException: Invalid boolean value 'hasRole('ROLE_ADMIN')'

Мой вывод:

Из (1) и (2) выше мы можем понять одну вещь. То есть кажется, что введенные значения помещаются в одинарные кавычки (' ') при передаче в аннотацию @PreAuthorize(...). Если это утверждение неверно, (1) и (2) не будут работать. Это только мой вывод!.

Когда мы приходим к (3), случай кажется похожим на (1) и (2). Значение в файле "hasRole('ROLE_ADMIN')". После правильного ввода этого значения, если при переходе к @PreAuthorize(...) будут добавлены одинарные кавычки, оно будет похоже на @PreAuthorize("'hasRole('ROLE_ADMIN')'"). Итак, «'hasRole('ROLE_ADMIN')'» — это строка, а не логическое значение. Это просто мой подозреваемый.

Вопрос:

Вы считаете мой вывод правильным? если нет, можете ли вы указать мне, есть ли что-то, что я пропустил? Или предоставьте мне, если у вас есть альтернативные решения для достижения @PreAuthorize(...) путем ввода значений из файла свойств.

Заранее спасибо!

Note: это не проблема конфигурации или инъекции. Я проверил, что значения введены правильно.


person eyasu    schedule 07.11.2013    source источник


Ответы (1)


Ключом к ответу является способ представления строковых литералов в SpEL. Следующие действительны:

  • Строковые литералы в SpEL представлены в одинарных кавычках, например, 'Hello' — это строковый литерал SpEL.
  • All the values from a resource bundle are converted to String literals, which means that:
    • If you fetch a HELLO from a bundle in Java, you will receive a "HELLO" String literal.
    • Если вы получите HELLO из пакета в SpEL, вы получите строковый литерал 'HELLO'.

Теперь давайте посмотрим на пример, который у вас есть выше.

  1. В вашем первом случае у вас есть role1=ROLE_ADMIN в комплекте ресурсов, что означает, что при оценке ${role1} будет создан строковый литерал 'ROLE_ADMIN'. Это приведет к аннотации @PreAuthorize("hasRole('ROLE_ADMIN')"), которая абсолютно действительна (если у вас определена роль ROLE_ADMIN). Вот почему это работает, и это не удивительно.

  2. Во втором случае у вас есть role2='ROLE_ADMIN' в комплекте ресурсов, что означает, что при оценке ${role2} будет создан строковый литерал '''ROLE_ADMIN'''. Обратите внимание, что знак ' экранируется двумя символами '. Вы получаете сообщение об ошибке «Отказано в доступе» просто потому, что у вас не роль 'ROLE_ADMIN', а роль ROLE_ADMIN (что отличается).

  3. Ваша третья догадка почти верна. Единственное, в чем вы не правы, так это в том, как будет выглядеть аннотация после оценки значения #{role3} в пакете ресурсов. Как я уже упоминал, ' экранируется в SpEL путем добавления двух символов '. Поэтому аннотация будет выглядеть как @PreAuthorize("'hasRole('''ROLE_ADMIN''')'"). Вы совершенно правы в своем предположении, что это выражение String, а не Boolean, и именно поэтому выбрасывается IllegalArgumentException.

person Konstantin Yovkov    schedule 07.11.2013
comment
Спасибо за укрепление моего предположения. Примечание. Мои первое и второе предположения совпадают с моим третьим :). Так что не ошибитесь в моем предположении (проверьте мою заключительную часть). Итак, каким будет решение? Если мы хотим вводить значения из файлов свойств в аннотации Spring, как мы можем этого добиться? Например, давайте рассмотрим приведенный выше пример. Я хочу поместить выражение hasRole('ROLE_ADMIN') в файл свойств и внедрить его в аннотацию @PreAuthorize(...). Как я могу включить SpEL, чтобы избежать одинарной кавычки (')? - person eyasu; 07.11.2013
comment
На вашем месте я бы создал собственный класс оценки выражений SpEL и зарегистрировал его как singleton bean. Затем я бы реализовал общий метод, который принимает переменную String в качестве аргумента (это будет выражение SpEL в формате String) и тип класса ожидаемого результата. В @PreAuthorize я бы вызвал универсальный метод и ожидал, что он вернет Boolean. Я могу сделать чат, если вы хотите expain вас в деталях. - person Konstantin Yovkov; 07.11.2013
comment
Еще раз спасибо. Я использовал свой собственный класс оценщика разрешений для оценки выражений. Но я решил не использовать настраиваемый оценщик разрешений, чтобы избежать сложности, которая может возникнуть при использовании настраиваемого оценщика. В частности, контекст, в котором я участвую, не настолько гибок, чтобы использовать мой настраиваемый оценщик. Да, было бы полезно, если бы мы могли немного поболтать. - person eyasu; 07.11.2013
comment
Нажмите здесь: чат .stackoverflow.com/rooms/40753/ - person Konstantin Yovkov; 07.11.2013