#xml #spring #spring-security
Вопрос:
Как бы вы сделали выражение, чтобы разрешить доступ ко всем ролям, кроме одной, без объявления их всех в spring-security.xml?
У нас есть четыре роли: private
, user1
, user2
и user3
. private
это единственная роль, которая может выполнять определенные службы. Другим разрешается только user1
, user2
и user3
.
<http pattern="/priv/**">
<intercept-url pattern="/**" access="hasRole('private')"/>
<http-basic/>
</http>
<http pattern="/pub/**">
<intercept-url pattern="/**" access="!hasRole('private')"/>
<http-basic/>
</http>
Я знаю, что при этом проблема была бы решена, но в случае пользователя, имеющего private
, user2
например, и, этот пользователь должен выполнить /priv/
/pub/
операцию и. Как можно настроить xml-файл?
Если у пользователя есть две роли ( private
и еще одна из других), будут разрешены обе операции.
Ответ №1:
Вы можете использовать RoleHierarchy
это для упрощения настройки безопасности.
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_PRIVATE > ROLE_USER
ROLE_USER > ROLE_USER1 > ROLE_USER2 > ROLE_USER3
</value>
</property>
</bean>
А затем в вашей http
конфигурации:
<http pattern="/priv/**">
<intercept-url pattern="/**" access="hasRole('PRIVATE')"/>
<http-basic/>
</http>
<http pattern="/pub/**">
<intercept-url pattern="/**" access="hasRole('USER')"/>
<http-basic/>
</http>
Таким образом, вы ROLE_USER
«встроите» все остальные ROLE_USERX
правила и ROLE_PRIVATE
встроите все из ROLE_USER
них .
Вам также следует обратиться к справочнику по безопасности Spring.
Комментарии:
1. Но дело в следующем: у меня могут быть новые различные разрешения, и все они, кроме частных, могут выполнять /pub/**. Я нахожу способ добавить новые разрешения и присоединиться к /pub без изменения spring-secutiry.xml избегая развертываний при каждом добавлении роли
2. Почему вы добавляете новую роль без другого доступа к управлению?
3. Поскольку единственная роль, которая не может получить доступ к /pub/, будет только «ЧАСТНОЙ», доступ будут иметь остальные, фактические и будущие роли. Кроме того, пользователь с частной и другой ролью должен получить доступ /паб/
Ответ №2:
Вы можете реализовать расширение WebSecurityExpressionRoot
с помощью метода boolean hasAnyRoleExcept(String... ignoredRoles)
эскиз (написан без поддержки IDE):
import org.springframework.security.core.authority.AuthorityUtils;
public class MyWebSecurityExpressionRoot extends WebSecurityExpressionRoot {
public MyWebSecurityExpressionRoot(final Authentication a, final FilterInvocation fi) {
super(a, fi);
}
public boolean hasAnyRoleExcept(String... ignoredRoles) {
//see SecurityExpressionRoot.hasAnyRole
Set<String> roles =
AuthorityUtils.authorityListToSet(
getAuthentication().getAuthorities());
//find a not ignored role
for (String role : roles) {
if (!ignoredRoles.contains(role)) {
return true;
}
}
return false;
}
}
Чтобы зарегистрировать его:
public class MyWebSecurityExpressionHandler extends DefaultWebSecurityExpressionHandler {
//Attention: override setTrustResolver too.
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
MyWebSecurityExpressionRoot root = new MyWebSecurityExpressionRoot(authentication, fi);
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
return root;
}
}
<security:http use-expressions="true" ...>
...
<security:expression-handler ref="myWebSecurityExpressionHandler"/>
<security:intercept-url pattern="/**" access="hasAnyRoleExcept('private')"/>
</security:http>
<bean id="myWebSecurityExpressionHandler" class="MyWebSecurityExpressionHandler"/>