如何实现自定义spring security acl?

Mor*_*ndi 3 java spring acl spring-security spring-security-acl

我正在使用 Spring 开发应用程序。在访问控制访问部分,我想使用 Spring Security Acl(我是 Acl 的新手)。我想基于 2 点在我的应用程序中实现 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",
   ...
}
Run Code Online (Sandbox Code Playgroud)

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

dac*_*una 8

您可以使用 Spring Security 实现一个简单的解决方案。这个想法是创建一个实现 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;
    }

}
Run Code Online (Sandbox Code Playgroud)

现在,通过此实现,您可以在例如您的服务层中使用 @PreAuthorize 注释,如下所示:

@PreAuthorize("hasPermission(#profile, 'update')")
public void updateUserProfileInASecureWay(UserProfile profile) {
    //code to update user profile
}
Run Code Online (Sandbox Code Playgroud)

@PreAuthorize 注释中的“hasPermission”从 updateUserProfileInASecureWay 方法的参数中接收 targetDomainObject #profile,并且我们传递所需的权限(在本例中为“更新”)。

此解决方案通过实施“小”ACL 避免了 ACL 的所有复杂性。也许它可以为你工作。