Spring Security中的拦截URL模式的顺序

IT小君   2023-10-24T23:45:51

在 appSecurity.xml 文件中,我有以下代码:

intercept-url pattern="/users/profile/**" access="hasRole('VIEW_PROFILES')".

intercept-url pattern="/users/profile/edit/**" access="hasRole('EDIT_PROFILES')"

我有一个页面 /users/profiles/edit/addnew ,当具有 VIEW_PROFILES 角色的用户尝试访问该页面时,他可以成功访问,但具有 EDIT_PROFILES 角色的用户无法访问。

我做错了什么?

评论(3)
IT小君

由于"/users/profile/edit/""/users/profile/"更具体,因此应该在列表中放在更靠前的位置。

为什么

模式总是按照它们定义的顺序进行评估。因此,更具体的模式应该在列表中定义得比不那么具体的模式更靠前。这在我们上面的例子中得到了反映,更具体的/secure/super/模式出现在不那么具体的/secure/模式之上。如果它们被调换,/secure/模式将始终匹配,/secure/super/模式将永远不会被评估。

来源:核心安全过滤器

2023-10-24T23:46:15   回复
IT小君

约翰·法雷利和Ritesh都是正确的。这些intercept-url模式按照所列顺序进行匹配。一旦找到匹配项,指定的剩余模式将被忽略。这就是为什么您应该尽量先列出更具体的模式。

在您的情况下,/users/profile/edit/somepage模式与第一个intercept-url模式中指定的模式匹配,因此Spring适当地检查该用户是否具有指定的访问角色。显然,您的EDIT_PROFILES用户没有VIEW_PROFILES权限,因此被拒绝访问。同样,您旨在限制对../edit/的访问仅限于具有EDIT_PROFILES权限的用户的做法受到了先前声明的影响,该声明允许具有VIEW_PROFILES权限的用户访问。

交换顺序可以简单解决问题,您可能还希望为EDIT_PROFILES用户添加VIEW_PROFILES权限(除了EDIT_PROFILES权限外)。然后,考虑使用access="hasAnyRole('REQUIRED_ROLE')"而不是access="hasRole('REQUIRED_ROLE')",以简化访问语句。

2023-10-24T23:46:46   回复
IT小君

确保您的EDIT_PROFILES规则位于VIEW_PROFILES规则之前。如果您查看VIEW_PROFILES的表达式,您会发现它包括了与EDIT_PROFILES匹配的所有URL。这意味着如果VIEW_PROFILES规则排在前面,Spring Security将不再尝试EDIT_PROFILES规则。

2023-10-24T23:46:51   回复