Spring Security 自定义PermissionEvaluator 进行数据权限校验和访问限制

Spring Security 可以使用ACL进行数据的权限访问,但是ACL过于复杂,对于简单的数据权限,我们只需要在查询方法上进行数据过滤就可以了。

自定义PermissionEvaluator

import java.io.Serializable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;

@Configuration
public class CustomPermissionEvaluator implements PermissionEvaluator {
    private static final Logger log = LoggerFactory.getLogger(CustomPermissionEvaluator.class);
    //普通的targetDomainObject判断
    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        log.error("-------------------------------------");
        return false;
    }
    //用于ACL的访问控制
    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        log.error("-------------------------------------");
        return false;
    }
}

配置GlobalMethodSecurityConfiguration

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    private CustomPermissionEvaluator customPermissionEvaluator;

    @Autowired
    public void setCustomPermissionEvaluator(CustomPermissionEvaluator customPermissionEvaluator) {
        this.customPermissionEvaluator = customPermissionEvaluator;
    }

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(customPermissionEvaluator);
        return expressionHandler;
        //return super.createExpressionHandler();
    }
}

需要注意的是,项目中不能有多个EnableGlobalMethodSecurity注解,不然会根据顺序加载不同导致未能正确加载自定义的config

权限验证 (PreAuthorize/PostAuthorize(EL中获取返回值:returnObject))

 /**
     * 修改密码.
     * @return
     */
    @PostMapping("/modifyPassword")
    @PreAuthorize("hasPermission(#baseReq,'read')")
    public ResponseEntity modifyPassword(@Valid @RequestBody BaseRequest baseReq, HttpServletRequest request) {
        Principal principal = SecurityContextHolder.getContext().getAuthentication();
        Map data = new HashMap<>();
        data.put("code", "fail");
        。。。
        return BaseResponse.success(data);
    }

这样的话,在CustomPermissionEvaluator的第一个方法会被调用,并传入参数,第一个是Security的authentication,第二个参数是就baseRequest对象,第三个参数是read。方法中获取到这三个参数可以判断,

  1. 如果有authentication中有read权限,返回true
  2. 如果baseRequest中的某个字段比如createid和authentication的id相同表示有权限,返回true
  3. 其他,返回false

过滤(PreFilter/PostFilter(EL中获取返回值:filterObject))

@GetMapping("/list")
@PostFilter("hasPermission(filterObject, 'read')")
public List list(){
    return jpa.findAll();
}

在自定义PermissionEvaluator,修改下判断方法,当返回false时,spring会把对象从list移除

if(targetDomainObject.getClass().isAssignableFrom(User.class)){
    User u = (User) targetDomainObject;
    if(u.getLogin().equals(authentication.getName())){
        return true;
    }
}
log.error("-------------------------------------");
return false;

你可能感兴趣的:(Spring Security 自定义PermissionEvaluator 进行数据权限校验和访问限制)