Просто чтобы узнать ACL, я пробовал с конфигурацией 4 таблиц acl. У меня есть таблица проекта (объект домена), я хочу достичь некоторой безопасности на уровне объекта домена. Он отлично работает с чтением объектов домена и отфильтровывает список, как и ожидалось
mask=1
и `
@PostFilter("hasPermission(filterObject, 'READ')")
public List<ProjectVO> listProject();
Выполнено: администратор может видеть все проекты, менеджер проектов может видеть проекты, для которых онэто менеджер ... Я не мог столкнуться с какой-либо проблемой с @PostFilter
и READ
Но я изменил метод проекта, как указано ниже
@PreAuthorize("hasPermission(#project, 'WRITE')")
public void modifyProject(Project project);
Это всегда дает мне AccessDeniedException какприведенные в журналах ниже
DEBUG - @org.springframework.security.access.prepost.PreAuthorize(value=hasPermission(#project, 'WRITE')) found on specific method: public void com.pvn.mvctiles.service.impl.ProjectServiceImpl.modifyProject(com.pvn.mvctiles.model.Project)
DEBUG - Caching method [CacheKey[com.pvn.mvctiles.service.impl.ProjectServiceImpl; public abstract void com.pvn.mvctiles.service.ProjectService.modifyProject(com.pvn.mvctiles.model.Project)]] with attributes [[authorize: 'hasPermission(#project, 'WRITE')', filter: 'null', filterTarget: 'null']]
DEBUG - Secure object: ReflectiveMethodInvocation: public abstract void com.pvn.mvctiles.service.ProjectService.modifyProject(com.pvn.mvctiles.model.Project); target is of class [com.pvn.mvctiles.service.impl.ProjectServiceImpl]; Attributes: [[authorize: 'hasPermission(#project, 'WRITE')', filter: 'null', filterTarget: 'null']]
DEBUG - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fec7843d: Principal: org.springframework.security.core.userdetails.User@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
DEBUG - Checking permission 'WRITE' for object 'org.springframework.security.acls.domain.ObjectIdentityImpl[Type: com.pvn.mvctiles.model.Project; Identifier: 1]'
DEBUG - Executing prepared SQL query
DEBUG - Executing prepared SQL statement [select acl_object_identity.object_id_identity, acl_entry.ace_order, acl_object_identity.id as acl_id, acl_object_identity.parent_object, acl_object_identity.entries_inheriting, acl_entry.id as ace_id, acl_entry.mask, acl_entry.granting, acl_entry.audit_success, acl_entry.audit_failure, acl_sid.principal as ace_principal, acl_sid.sid as ace_sid, acli_sid.principal as acl_principal, acli_sid.sid as acl_sid, acl_class.class from acl_object_identity left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid left join acl_class on acl_class.id = acl_object_identity.object_id_class left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity left join acl_sid on acl_entry.sid = acl_sid.id where ( (acl_object_identity.object_id_identity = ? and acl_class.class = ?)) order by acl_object_identity.object_id_identity asc, acl_entry.ace_order asc]
DEBUG - Fetching JDBC Connection from DataSource
DEBUG - Returning false - no ACLs apply for this principal
DEBUG - Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@71322d20, returned: -1
DEBUG - Voter: org.springframework.security.access.vote.RoleVoter@30750dc0, returned: 0
DEBUG - Voter: org.springframework.security.access.vote.AuthenticatedVoter@69e7d03e, returned: 0
TRACE - Returning cached instance of singleton bean 'delegatingApplicationListener'
TRACE - Returning cached instance of singleton bean 'delegatingApplicationListener'
TRACE - Failed to complete request
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy259.modifyProject(Unknown Source)
at com.pvn.mvctiles.controller.ProjectController.modifyProject(ProjectController.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
acl содержание таблицы
Я не мог понять, что не так. Мои конфигурации
Внедрение GlobalMethodSecurityConfiguration @Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class AclMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration
{
@Autowired
MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler()
{
return defaultMethodSecurityExpressionHandler;
}
}
MethodSecurityExpressionHandler конфигурация компонента @Configuration
public class AclConfiguration
{
@Autowired
DataSource dataSource;
@Bean
public MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler()
{
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
AclPermissionEvaluator permissionEvaluator = new AclPermissionEvaluator(aclService());
expressionHandler.setPermissionEvaluator(permissionEvaluator);
return expressionHandler;
}
@Bean
public JdbcMutableAclService aclService()
{
return new JdbcMutableAclService(
dataSource, lookupStrategy(), aclCache());
}
@Bean
public AclAuthorizationStrategy aclAuthorizationStrategy()
{
return new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_ADMIN"));
}
@Bean
public PermissionGrantingStrategy permissionGrantingStrategy()
{
return new DefaultPermissionGrantingStrategy(
new ConsoleAuditLogger());
}
@Bean
public EhCacheBasedAclCache aclCache()
{
return new EhCacheBasedAclCache(
aclEhCacheFactoryBean().getObject(),
permissionGrantingStrategy(),
aclAuthorizationStrategy()
);
}
@Bean
public EhCacheFactoryBean aclEhCacheFactoryBean()
{
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
ehCacheFactoryBean.setCacheName("aclCache");
return ehCacheFactoryBean;
}
@Bean
public EhCacheManagerFactoryBean aclCacheManager()
{
EhCacheManagerFactoryBean ehcm = new EhCacheManagerFactoryBean();
ehcm.setShared(true);
return ehcm;
}
@Bean
public LookupStrategy lookupStrategy()
{
return new BasicLookupStrategy(
dataSource,
aclCache(),
aclAuthorizationStrategy(),
new ConsoleAuditLogger()
);
}
}