Spring可以评估SpEL表达式中的所有字符/表达式,因为它们是从属性文件中注入的吗?
我想知道为什么spring不会直接评估所有表达式,因为它们是从属性文件注入到@PreAuthorize(...)
注释中的。 我认为spring不会评估某些字符,如’(’,’)’,”’等,或者它会在属性文件中注入的值之上添加特殊字符。 为了澄清,让我们考虑以下示例。
@PreAuthorize("hasRole('ROLE_ADMIN')")
上面的表达是正常的,并且工作正常。 假设属性文件的值如下。
role1=ROLE_ADMIN role2='ROLE_ADMIN' role3=hasRole('ROLE_ADMIN')
-
让我们从属性文件中注入
role1
并将其传递给@PreAuthorize("hasRole(${role1})")
,它工作正常。 在评估hasRole(...)
表达式的正常方式中,角色名称必须在单引号下,即'ROLE_ADMIN'
。 但这里它适用于ROLE_ADMIN。 奇怪!。 -
如果我们将
role2
从属性文件注入@PreAuthorize("hasRole(${role2})")
,它将返回拒绝访问。 这意味着它被评估但我们可以意识到传递给表达式的值不是“'ROLE_ADMIN'
”。 因此,如果角色名称在单引号下,则拒绝访问。 另一个惊喜! -
如果我们尝试将
role3
从属性文件注入@PreAuthorize("${role3}")
,那么它也不会被评估。 例外:-
java.lang.IllegalArgumentException: Failed to evaluate expression 'role3'
: -
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
:它既不是配置问题也不是注入问题。 我检查了值是否正确注入。
答案的关键是如何在SpEL中表示String文字。 以下是有效的:
- SpEL中的字符串文字用单引号表示,例如
'Hello'
是SpEL字符串文字。 - 资源包中的所有值都将转换为字符串文字,这意味着:
- 如果从Java中的bundle中获取
HELLO
,您将收到一个"HELLO"
字符串文字。 - 如果你从SpEL中的一个包中获取
HELLO
,你将收到一个'HELLO'
字符串文字。
- 如果从Java中的bundle中获取
现在让我们来看看你上面的例子。
-
在第一种情况下,资源包中有
role1=ROLE_ADMIN
,这意味着在评估${role1}
时将创建一个'ROLE_ADMIN'
字符串文字。 这将导致@PreAuthorize("hasRole('ROLE_ADMIN')")
注释完全有效(如果您定义了ROLE_ADMIN角色)。 这就是它工作的原因, 并不奇怪。 -
在第二种情况下,资源包中有
role2='ROLE_ADMIN'
,这意味着在评估${role2}
时将创建'''ROLE_ADMIN'''
字符串文字。 请注意,'
标记通过放置两个'
字符进行转义。 您收到“拒绝访问”错误,原因只是因为您没有'ROLE_ADMIN'
角色,而是ROLE_ADMIN
(不同)。 -
你的第三个猜测几乎是正确的。 您唯一不正确的是注释在评估资源包中的
#{role3}
值时的#{role3}
。 正如我所提到的,'
在SpEL中通过放置两个'
字符进行转义。 因此,注释看起来像@PreAuthorize("'hasRole('''ROLE_ADMIN''')'")
。 你假设这是一个String
,而不是一个Boolean
表达式,这是完全正确的,这就是抛出IllegalArgumentException
原因。