[英]How to implement Custom spring security acl?
我正在使用Spring开发应用程序。 在“访问控制访问”部分,我想使用Spring Security Acl(我是Acl的新手)。 我想基于两点在我的应用程序中实现ACL:
read
, create
, modify
, delete
和Administrator
。 create
权限时,它应该能够read
,或者当拥有modify
权限时,它应该能够read
, create
和modify
等。 可能吗? 怎么样?
更新 :
我的应用程序基于Spring MVC RESTFUL。 当用户想要修改自己的信息时,他使用Ajax发送一些json数据。 json数据的示例如下:
{
"id": 1,//user Id
"name": "my name",
"password": "my password",
"email": "email@email.com",
...
}
现在,恶意用户可以登录自己的帐户。 该用户可以像其他所有用户一样modify
其数据。 在他发送数据之前,请更改其ID,然后modify
另一个帐户用户信息。 我想使用ACL来防止这种颠覆性工作。 用户可以访问其他用户,其他人可以修改其信息。
您可以使用spring安全性实现一个简单的解决方案。 这个想法是创建一个实现org.springframework.security.access.PermissionEvaluator的类,并重写hasPermission方法。 看下一个例子:
@Component("permissionEvaluator")
public class PermissionEvaluator implements org.springframework.security.access.PermissionEvaluator {
/**
* @param authentication represents the user in question. Should not be null.
* @param targetDomainObject the domain object for which permissions should be
* checked. May be null in which case implementations should return false, as the null
* condition can be checked explicitly in the expression.
* @param permission a representation of the permission object as supplied by the
* expression system. Not null.
* @return true if the permission is granted, false otherwise
*/
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
if (authentication != null && permission instanceof String) {
User loggedUser = (User) authentication.getPrincipal();
String permissionToCheck = (String) permission;
// in this part of the code you need to check if the loggedUser has the "permission" over the
// targetDomainObject. In this implementation the "permission" is a string, for example "read", or "update"
// The targetDomainObject is an actual object, for example a object of UserProfile class (a class that
// has the profile information for a User)
// You can implement the permission to check over the targetDomainObject in the way that suits you best
// A naive approach:
if (targetDomainObject.getClass().getSimpleName().compareTo("UserProfile") == 0) {
if ((UserProfile) targetDomainObject.getId() == loggedUser.getId())
return true;
}
// A more robust approach: you can have a table in your database holding permissions to each user over
// certain targetDomainObjects
List<Permission> userPermissions = permissionRepository.findByUserAndObject(loggedUser,
targetDomainObject.getClass().getSimpleName());
// now check if in userPermissions list we have the "permission" permission.
// ETC...
}
//access denied
return false;
}
}
现在,通过此实现,您可以在服务层中使用@PreAuthorize注释,如下所示:
@PreAuthorize("hasPermission(#profile, 'update')")
public void updateUserProfileInASecureWay(UserProfile profile) {
//code to update user profile
}
@PreAuthorize批注中的“ hasPermission”从updateUserProfileInASecureWay方法的参数中接收targetDomainObject #profile,并且我们还传递了所需的权限(在本例中为“ update”)。
该解决方案通过实现“小型” ACL避免了ACL的所有复杂性。 也许它可以为您工作。
您可以使用以下示例中使用的角色层次结构组合。Spring acl具有基本权限,如果要实现自定义权限,则需要创建一个自定义Permission类,以扩展api中的Base Permissions类。 我们可以为每种权限定义角色,并如下定义角色层次结构。
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator" />
<property name="roleHierarchy" ref="roleHierarchy" />
</bean>
<!-- A customized PermissionEvaluator that evaluates permissions via the ACL module -->
<bean class="org.springframework.security.acls.AclPermissionEvaluator" id="permissionEvaluator">
<!-- Reference to the ACL service which performs JDBC calls to an ACL database -->
<constructor-arg ref="aclService"/>
<property name="permissionFactory" ref="customPermissionFactory" />
</bean>
<bean id="customPermissionFactory" class="org.krams.tutorial.security.CustomPermissionFactory"></bean>
<!-- A customized ACL service which provides default JDBC implementation -->
<bean class="org.springframework.security.acls.jdbc.JdbcMutableAclService" id="aclService">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="lookupStrategy"/>
<constructor-arg ref="aclCache"/>
</bean>
<!-- A lookup strategy for optimizing database queries -->
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="aclCache"/>
<constructor-arg ref="aclAuthorizationStrategy"/>
<constructor-arg ref="auditLogger"/>
<property name="permissionFactory" ref="customPermissionFactory"/>
</bean>
<!-- A MySQL datasource with pooling capabalities for the ACL module -->
<!-- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://localhost/acl"
p:user="root"
p:password=""
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10" /> -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:tcp://localhost/~/springsecurity" />
<!--<property name="url" value="jdbc:h2:tcp://ggk-wrl-win1/~/dev" /> -->
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<!-- An ACL cache to minimize calls to the ACL database -->
<bean id="aclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
<constructor-arg>
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
</property>
<property name="cacheName" value="aclCache"/>
</bean>
</constructor-arg>
</bean>
<!-- An ACL authorization strategy to determine whether a principal is permitted to call administrative methods -->
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.GrantedAuthorityImpl">
<constructor-arg value="ROLE_USER"/>
</bean>
<bean class="org.springframework.security.core.authority.GrantedAuthorityImpl">
<constructor-arg value="ROLE_USER"/>
</bean>
<bean class="org.springframework.security.core.authority.GrantedAuthorityImpl">
<constructor-arg value="ROLE_USER"/>
</bean>
</list>
</constructor-arg>
</bean>
<!-- An audit logger used to log audit events -->
<bean id="auditLogger" class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
<!-- Defines the role order -->
<!-- http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.html -->
<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_ADMIN > ROLE_USER
ROLE_USER > ROLE_VISITOR
</value>
</property>
</bean>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.