有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何实现定制的spring安全acl?

我正在使用Spring开发一个应用程序。在访问控制部分,我想使用SpringSecurityACL(我是Acl新手)。我想在我的应用程序中基于两点实现ACL:

  1. 应用程序应该有五个权限:readcreatemodifydeleteAdministrator
  2. 权限是层次结构,当用户拥有create权限时,它应该能够read,或者当用户拥有modify权限时,它应该能够readcreatemodify等等

可能吗?怎么做

更新
我的应用程序基于Spring MVC RESTFUL。当用户想要修改自己的信息时,他会使用Ajax发送一些json数据。json数据的示例如下所示:

{
  "id": 1,//user Id
  "name": "my name",
  "password": "my password",
  "email": "email@email.com",
   ...
}

现在,恶意用户可以登录到自己的帐户。此用户可以像所有其他用户一样modify其数据。在他发送数据之前,更改他的id和modify另一个帐户用户信息。我想使用ACL来防止这种颠覆性的工作。用户可以访问其他人,其他人可以修改他的信息


共 (2) 个答案

  1. # 1 楼答案

    您可以使用spring security实现一个简单的解决方案。其想法是创建一个实现org的类。springframework。安全通道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的所有复杂性。也许这对你有用

  2. # 2 楼答案

    您可以使用以下示例中使用的角色层次结构组合。Spring acl具有基本权限,如果要实现自定义权限,需要在api中创建扩展基本权限类的自定义权限类。我们可以为每种权限定义角色,并定义角色层次结构,如下所示

    <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>