ofbiz中各类安全代码解析

security.hasPermission方法

public boolean hasPermission(String permission, GenericValue userLogin) {
        if (userLogin == null) return false;
//查找出用户对应的安全组
        Iterator<GenericValue> iterator = findUserLoginSecurityGroupByUserLoginId(userLogin.getString("userLoginId"));
        GenericValue userLoginSecurityGroup = null;

//遍历每个组,查看是否这个组拥有这个权限
        while (iterator.hasNext()) {
            userLoginSecurityGroup = iterator.next();
            if (securityGroupPermissionExists(userLoginSecurityGroup.getString("groupId"), permission)) return true;
        }

        return false;
    }


而对于查找用户对应的组则很简单
collection = delegator.findByAnd("UserLoginSecurityGroup", UtilMisc.toMap("userLoginId", userLoginId), null);
查找表UserLoginSecurityGroup中userLoginid的信息
,再通过
collection = EntityUtil.filterByDate(collection, true);
过滤掉已经能够过期的组


securityGroupPermissionExists
方法也比较简单,是
从SecurityGroupPermission表读出一条permissionId=我们需要检查的权限groupId是当前组的id,如果结果不是null,就是存在这个权限了。

服务的授权代码
在ServiceDispatcher中(10.4版本代码,443行)代码
context = checkAuth(localName, context, modelService);
这是检查的代码,进入代码查看
,这里删除了一部分代码
private Map<String, Object> checkAuth(String localName,
Map<String, Object> context, ModelService origService)
throws ServiceAuthException, GenericServiceException {
DispatchContext dctx = this.getLocalContext(localName);
//这是处理service中的<permission-service service-name=""/>元素的。它会负责调用这个service,这个service需要返回一个Boolean hasPermission,来决定是否权限通过。
if (UtilValidate.isNotEmpty(origService.permissionServiceName)) {
Map<String, Object> permResp = origService.evalPermission(dctx,
context);
Boolean hasPermission = (Boolean) permResp.get("hasPermission");
if (hasPermission == null) {
throw new ServiceAuthException(
"ERROR: the permission-service ["
+ origService.permissionServiceName
+ "] did not return a result. Not running the service ["
+ origService.name + "]");
}
if (hasPermission.booleanValue()) {
context.putAll(permResp);
context = origService.makeValid(context, ModelService.IN_PARAM);
} else {
//很明显,未通过,赏它一段未通过的信息。
String message = (String) permResp.get("failMessage");
if (UtilValidate.isEmpty(message)) {
message = ServiceUtil.getErrorMessage(permResp);
}
if (UtilValidate.isEmpty(message)) {
message = "You do not have permission to invoke the service ["
+ origService.name + "]";
}
throw new ServiceAuthException(message);
}
} else {
//事件的权限处理origService.evalPermissions,进去look。
if (!origService.evalPermissions(dctx, context)) {
Locale l = (Locale) context.get("locale");
throw new ServiceAuthException(UtilProperties.getMessage(
"ServiceError", "Service.Auth", l)
+ "[" + origService.name + "]");
}
}

return context;
}


//没的神马东西,看来还得往里进,这里只要知道permissionGroups里面的是要检查的所有的权限内容。

<required-permissions join-type="AND">
<check-permission permission="TEST_VIEW" />
</required-permissions>
那么只有一个required-permissions,那permissionGroups只有一个对象(size=1)
public boolean evalPermissions(DispatchContext dctx, Map<String, ? extends Object> context) {
        // old permission checking
        if (this.containsPermissions()) {
            for (ModelPermGroup group: this.permissionGroups) {
                if (!group.evalPermissions(dctx, context)) {
                    return false;
                }
            }
            return true;
        } else {
            return true;
        }
    }


//进入group.evalPermissions(dctx, context)方法

public boolean evalPermissions(DispatchContext dctx, Map<String, ? extends Object> context) {
//这里的permissions就是required-permission中的check-permission之类的子元素,类型是org.ofbiz.service.ModelPermission
        if (UtilValidate.isNotEmpty(permissions))  {
            boolean foundOne = false;
            for (ModelPermission perm: permissions) {
//这里还要再调用evalPermission来处理权限
                if (perm.evalPermission(dctx, context)) {
                    foundOne = true;
                } else {
                    if (joinType.equals(PERM_JOIN_AND)) {
                        return false;
                    }
                }
            }
            return foundOne;
        } else {
            return true;
        }
    }

//继续进入evalPermission
public boolean evalPermission(DispatchContext dctx, Map<String, ? extends Object> context) {
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Authorization authz = dctx.getAuthorization();
        Security security = dctx.getSecurity();
//没登陆,肯定直接pass了。
        if (userLogin == null) {
            Debug.logInfo("Secure service requested with no userLogin object", module);
            return false;
        }

//有类型的,PERMISSION,简单的类型
        switch (permissionType) {
            case PERMISSION:
                return evalAuthzPermission(authz, userLogin, context);
ENTITY_PERMISSION是permission+action的类型
            case ENTITY_PERMISSION:
                return evalEntityPermission(security, userLogin);
ROLE_MEMBER角色检查
            case ROLE_MEMBER:
                return evalRoleMember(userLogin);
PERMISSION_SERVICE使用服务方式处理的权限类型。,在required-permissions自然也可以包含permission-service
            case PERMISSION_SERVICE:
                return evalPermissionService(serviceModel, dctx, context);
            default:
                Debug.logWarning("Invalid permission type [" + permissionType + "] for permission named : " + nameOrRole + " on service : " + serviceModel.name, module);

简单的处理方式
private boolean evalAuthzPermission(Authorization authz, GenericValue userLogin, Map<String, ? extends Object> context) {
        if (nameOrRole == null) {
            Debug.logWarning("Null permission name passed for evaluation", module);
            return false;
        }
//authz是Authorization类,也没有必要再看下去了,这里是查找出这个用户当前所有的组,再看组里面有没有这个权限。
        return authz.hasPermission(userLogin.getString("userLoginId"), nameOrRole, context);


    }

                return false;
        }
    }

再看ENTITY_PERMISSION类型的权限检查
它是调用
private boolean evalEntityPermission(Security security, GenericValue userLogin) {
        if (nameOrRole == null) {
            Debug.logWarning("Null permission name passed for evaluation", module);
            return false;
        }
        if (action == null) {
            Debug.logWarning("Null action passed for evaluation",  module);
        }
        return security.hasEntityPermission(nameOrRole, action, userLogin);
    }
实际上是通过Security 的hasEntityPermission方法类处理。
再其内部实际上可以看到的是(entity就是<check-permission permission="TEST_VIEW" />中的permission)
// always try _ADMIN first so that it will cache first, keeping the cache smaller
            if (securityGroupPermissionExists(userLoginSecurityGroup.getString("groupId"), entity + "_ADMIN"))
                return true;
            if (securityGroupPermissionExists(userLoginSecurityGroup.getString("groupId"), entity + action))
                return true;
它会对permission+action何permission+_ADMIN两者一起进行处理。


ROLE_MEMBER
evalEntityPermission方法,具体内容暂时不看了。

你可能感兴趣的:(ofbiz)