3

Springを使用してアプリケーションを開発しています。Access Control Access セクションでは、Spring Security Acl を使用したいと考えています (Acl は初めてです)。次の 2 つの点に基づいて、アプリケーションに ACL を実装したいと考えています。

  1. アプリケーションには、readcreate、 の5つの権限が必要です。modifydeleteAdministrator
  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 を使用して、この Subversive 作業を防止したいと考えています。また、ユーザーは、他のユーザーが自分の情報を変更できるように、他のユーザーにアクセスできます。

4

2 に答える 2

8

春のセキュリティを使用して簡単なソリューションを実装できます。アイデアは、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 の複雑さをすべて回避します。多分それはあなたのために働くことができます。

于 2016-04-19T17:29:12.447 に答える
0

次の例で使用されているように、ロール階層の組み合わせを使用できます。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>
于 2016-05-31T12:50:56.863 に答える