先上一张大家都很熟悉的图
[img]http://dl.iteye.com/upload/attachment/432432/5095700f-ae44-3f42-b634-47220fce6376.png[/img]
这张图可以说是整个liferay的核心,他和权限密不可分,在权限体系里,每一个箭头和UI设置和API一一对应,今天讲权限,不讲代码只讲理论。liferay的权限策略分为五种,默认是采用第五种,因为第五种性能最好,如果要修改则在portal-ext.properies加上permissions.user.check.algorithm=3
讲策略之前我们先讲一下,liferay权限分为几种
A:Group Role Permission: 用户加入的Group(Community/Organization)所拥有的角色的权限
Is the user connected to one of the permissions via group or organization roles?
B:Group Permission: 分配给Group(包括Community/Organization/User Group三类Group)的权限
Is the user associated with groups or organizations that are directly connected to one of the permissions?
C:User Role Permission: 分配给用户Regular类型角色的权限
Is the user connected to one of the permissions via user roles?
D:User Group Role Permission: 用户加Group(Community/Organization)所拥有该社区角色的权限
Is the user connected to one of the permissions via user group roles?
E:User Permission: 直接分配给user的权限
Is the user directly connected to one of the permissions?
F:Role Permission: 分配给角色(包括Regular/Community/Organization三种类型角色)的权限
Is the user associated with a role that is directly connected to one of the permissions?
讲完了这check权限的分类,我们现在开始讲liferay的权限策略
Algorithm 1. A or B or C or D or E
Algorithm 2. A and B and C and D and E
Algorithm 3. B or E or F
Algorithm 4. B and E and F
Algorithm 5. F
注意:liferay推荐使用第五种是因为他效率最高,第一、二种是不可能会用到的,因为那是早期版本的设计,有些表例如:Groups_Roles都已经放弃了。如果不是必须不要去修改策略。
现在说说他的缺点:用过权限开发的人都会发现,他的权限粒度很高,这样带来了一个问题就是效率会变低(虽然他用了大量的cache),最讨厌的是liferay权限体系总是,先把数据全搜索出来,当你要进行操作(VIEW)时,他才会跳出个红框框告诉你,你没有权限,这样很不友好。最典型的是list分页,点其中一条才会告诉你没权限,客户居然投诉:说我们有诱导之嫌。liferay现有的api是肯定做不到直接搜索出合法数据,虽然liferay在有的元素的service层,先把数据全取出来然后再一个一个的过滤来达到这样的效果,这样我觉得实在无法容忍,为了一页20条的数据,你居然要搜索出所有数据。为此我在项目中专门写了一个类,把一些共用的权限sql写了出来
注意:我们到的是策略3,所以我分别写了B,E,F权限SQL,及一个总的Algorithm3SQL,这些SQL返回的都是你要搜索元素的key,这些SQL在liferay中是通用的,只要你是用的liferay的权限他都是合适的,你要把他放在你sql合适的位置,注意最好不要使用in,这样效率是比较低的。
[img]http://dl.iteye.com/upload/attachment/432432/5095700f-ae44-3f42-b634-47220fce6376.png[/img]
这张图可以说是整个liferay的核心,他和权限密不可分,在权限体系里,每一个箭头和UI设置和API一一对应,今天讲权限,不讲代码只讲理论。liferay的权限策略分为五种,默认是采用第五种,因为第五种性能最好,如果要修改则在portal-ext.properies加上permissions.user.check.algorithm=3
讲策略之前我们先讲一下,liferay权限分为几种
A:Group Role Permission: 用户加入的Group(Community/Organization)所拥有的角色的权限
Is the user connected to one of the permissions via group or organization roles?
<sql id="com.liferay.portal.service.persistence.PermissionFinder.countByGroupsRoles">
<![CDATA[
SELECT
COUNT(*) AS COUNT_VALUE
FROM
Groups_Roles
INNER JOIN
Roles_Permissions ON
(Roles_Permissions.roleId = Groups_Roles.roleId)
INNER JOIN
Permission_ ON
(Permission_.permissionId = Roles_Permissions.permissionId)
WHERE
([$PERMISSION_IDS$]) AND
([$GROUP_IDS$])
]]>
</sql>
B:Group Permission: 分配给Group(包括Community/Organization/User Group三类Group)的权限
Is the user associated with groups or organizations that are directly connected to one of the permissions?
<sql id="com.liferay.portal.service.persistence.PermissionFinder.countByGroupsPermissions">
<![CDATA[
SELECT
COUNT(*) AS COUNT_VALUE
FROM
Permission_
INNER JOIN
Groups_Permissions ON
(Groups_Permissions.permissionId = Permission_.permissionId)
WHERE
([$PERMISSION_IDS$]) AND
([$GROUP_IDS$])
]]>
</sql>
C:User Role Permission: 分配给用户Regular类型角色的权限
Is the user connected to one of the permissions via user roles?
<sql id="com.liferay.portal.service.persistence.PermissionFinder.countByUsersRoles">
<![CDATA[
SELECT
COUNT(*) AS COUNT_VALUE
FROM
Users_Roles
INNER JOIN
Roles_Permissions ON
(Roles_Permissions.roleId = Users_Roles.roleId)
INNER JOIN
Permission_ ON
(Permission_.permissionId = Roles_Permissions.permissionId)
WHERE
([$PERMISSION_IDS$]) AND
(Users_Roles.userId = ?)
]]>
</sql>
D:User Group Role Permission: 用户加Group(Community/Organization)所拥有该社区角色的权限
Is the user connected to one of the permissions via user group roles?
<sql id="com.liferay.portal.service.persistence.PermissionFinder.countByUserGroupRole">
<![CDATA[
SELECT
COUNT(*) AS COUNT_VALUE
FROM
UserGroupRole
INNER JOIN
Roles_Permissions ON
(Roles_Permissions.roleId = UserGroupRole.roleId and UserGroupRole.groupId = ?)
INNER JOIN
Permission_ ON
(Permission_.permissionId = Roles_Permissions.permissionId)
WHERE
([$PERMISSION_IDS$]) AND
(UserGroupRole.userId = ?)
]]>
</sql>
E:User Permission: 直接分配给user的权限
Is the user directly connected to one of the permissions?
<sql id="com.liferay.portal.service.persistence.PermissionFinder.countByUsersPermissions">
<![CDATA[
SELECT
COUNT(*) AS COUNT_VALUE
FROM
Permission_
INNER JOIN
Users_Permissions ON
(Users_Permissions.permissionId = Permission_.permissionId)
WHERE
([$PERMISSION_IDS$]) AND
(Users_Permissions.userId = ?)
]]>
</sql>
F:Role Permission: 分配给角色(包括Regular/Community/Organization三种类型角色)的权限
Is the user associated with a role that is directly connected to one of the permissions?
<sql id="com.liferay.portal.service.persistence.PermissionFinder.countByUsersPermissions">
<![CDATA[
SELECT
COUNT(*) AS COUNT_VALUE
FROM
Permission_
INNER JOIN
Users_Permissions ON
(Users_Permissions.permissionId = Permission_.permissionId)
WHERE
([$PERMISSION_IDS$]) AND
(Users_Permissions.userId = ?)
]]>
</sql>
讲完了这check权限的分类,我们现在开始讲liferay的权限策略
Algorithm 1. A or B or C or D or E
Algorithm 2. A and B and C and D and E
Algorithm 3. B or E or F
Algorithm 4. B and E and F
Algorithm 5. F
注意:liferay推荐使用第五种是因为他效率最高,第一、二种是不可能会用到的,因为那是早期版本的设计,有些表例如:Groups_Roles都已经放弃了。如果不是必须不要去修改策略。
现在说说他的缺点:用过权限开发的人都会发现,他的权限粒度很高,这样带来了一个问题就是效率会变低(虽然他用了大量的cache),最讨厌的是liferay权限体系总是,先把数据全搜索出来,当你要进行操作(VIEW)时,他才会跳出个红框框告诉你,你没有权限,这样很不友好。最典型的是list分页,点其中一条才会告诉你没权限,客户居然投诉:说我们有诱导之嫌。liferay现有的api是肯定做不到直接搜索出合法数据,虽然liferay在有的元素的service层,先把数据全取出来然后再一个一个的过滤来达到这样的效果,这样我觉得实在无法容忍,为了一页20条的数据,你居然要搜索出所有数据。为此我在项目中专门写了一个类,把一些共用的权限sql写了出来
public static String getPrimkeyByRolePermission(long companyId,
String name, int scope, String actionId, String roleIds){
StringBuffer sql = new StringBuffer();
sql.append("SELECT DISTINCT RESOURCE_.PRIMKEY FROM RESOURCE_ "+
"LEFT JOIN RESOURCECODE ON (RESOURCE_.CODEID = RESOURCECODE.CODEID) "+
"LEFT JOIN PERMISSION_ ON (PERMISSION_.RESOURCEID = RESOURCE_.RESOURCEID) "+
"LEFT JOIN ROLES_PERMISSIONS ON (PERMISSION_.PERMISSIONID = ROLES_PERMISSIONS.PERMISSIONID) ");
sql.append("WHERE RESOURCECODE.COMPANYID = "+ companyId +" " +
"AND RESOURCECODE.NAME = '"+ name +"' AND RESOURCECODE.SCOPE = "+ scope +" ");
sql.append("AND PERMISSION_.COMPANYID = "+ companyId +
" AND PERMISSION_.ACTIONID = '"+ actionId +"' AND " +
"ROLES_PERMISSIONS.ROLEID IN ("+ roleIds +")");
return sql.toString();
}
public static String getPrimkeyByRolePermission(long companyId,
String name, int scope, String actionId, long userId){
StringBuffer sql = new StringBuffer();
sql.append("SELECT DISTINCT RESOURCE_.PRIMKEY FROM RESOURCE_ "+
"LEFT JOIN RESOURCECODE ON (RESOURCE_.CODEID = RESOURCECODE.CODEID) "+
"LEFT JOIN PERMISSION_ ON (PERMISSION_.RESOURCEID = RESOURCE_.RESOURCEID) "+
"LEFT JOIN USERS_PERMISSIONS ON (PERMISSION_.PERMISSIONID = USERS_PERMISSIONS.PERMISSIONID) ");
sql.append("WHERE RESOURCECODE.COMPANYID = "+ companyId +" " +
"AND RESOURCECODE.NAME = '"+ name +"' AND RESOURCECODE.SCOPE = "+ scope +" ");
sql.append("AND PERMISSION_.COMPANYID = "+ companyId +
" AND PERMISSION_.ACTIONID = '"+ actionId +"' AND " +
"USERS_PERMISSIONS.USERID = " + userId) ;
return sql.toString();
}
public static String getPrimkeyByGroupPermission(long companyId,
String name, int scope, String actionId, long userId, long groupId){
StringBuffer sql = new StringBuffer();
sql.append("SELECT DISTINCT RESOURCE_.PRIMKEY FROM RESOURCE_ "+
"LEFT JOIN RESOURCECODE ON (RESOURCE_.CODEID = RESOURCECODE.CODEID) "+
"LEFT JOIN PERMISSION_ ON (PERMISSION_.RESOURCEID = RESOURCE_.RESOURCEID) "+
"LEFT JOIN GROUPS_PERMISSIONS ON (PERMISSION_.PERMISSIONID = GROUPS_PERMISSIONS.PERMISSIONID) +" +
"LEFT JOIN USERS_GROUPS ON (GROUPS_PERMISSIONS.GROUPID = USERS_GROUPS.GROUPID) ");
sql.append("WHERE RESOURCECODE.COMPANYID = "+ companyId +" " +
"AND RESOURCECODE.NAME = '"+ name +"' AND RESOURCECODE.SCOPE = "+ scope +" ");
sql.append("AND PERMISSION_.COMPANYID = "+ companyId +
" AND PERMISSION_.ACTIONID = '"+ actionId +"' AND " +
"GROUPS_PERMISSIONS.GROUPID = " + groupId +" AND " +
"USERS_GROUPS.USERID = " + userId) ;
return sql.toString();
}
public static String getPrimkeyByPermissionAlgorithm3(long companyId,
String name, int scope, String actionId, long userId, long groupId){
StringBuffer sql = new StringBuffer();
sql.append("SELECT DISTINCT RESOURCE_.PRIMKEY ID FROM RESOURCE_, RESOURCECODE, PERMISSION_, ");
sql.append("(");
sql.append("SELECT ROLES_PERMISSIONS.PERMISSIONID FROM ROLES_PERMISSIONS " +
"JOIN USERS_ROLES ON (ROLES_PERMISSIONS.ROLEID = USERS_ROLES.USERID) " +
"WHERE USERS_ROLES.USERID = " + userId);
sql.append(") AS R, ");
sql.append("(");
sql.append("SELECT USERS_PERMISSIONS.PERMISSIONID FROM USERS_PERMISSIONS " +
"WHERE USERS_PERMISSIONS.USERID = " + userId);
sql.append(") AS U, ");
sql.append("(");
sql.append("SELECT GROUPS_PERMISSIONS.PERMISSIONID FROM GROUPS_PERMISSIONS " +
"JOIN USERS_GROUPS ON (GROUPS_PERMISSIONS.GROUPID = USERS_GROUPS.GROUPID) " +
"WHERE USERS_GROUPS.GROUPID = " + groupId);
sql.append(") AS G ");
sql.append("WHERE RESOURCECODE.COMPANYID = "+ companyId +" " +
"AND RESOURCECODE.NAME = '"+ name +"' AND RESOURCECODE.SCOPE = "+ scope +" ");
sql.append("AND PERMISSION_.COMPANYID = "+ companyId +
" AND PERMISSION_.ACTIONID = '"+ actionId + "' ") ;
sql.append("AND RESOURCE_.CODEID = RESOURCECODE.CODEID "+
"AND PERMISSION_.RESOURCEID = RESOURCE_.RESOURCEID ");
sql.append("AND (PERMISSION_.PERMISSIONID = R.PERMISSIONID OR " +
"PERMISSION_.PERMISSIONID = U.PERMISSIONID OR " +
"PERMISSION_.PERMISSIONID = G.PERMISSIONID)" );
return sql.toString();
}
注意:我们到的是策略3,所以我分别写了B,E,F权限SQL,及一个总的Algorithm3SQL,这些SQL返回的都是你要搜索元素的key,这些SQL在liferay中是通用的,只要你是用的liferay的权限他都是合适的,你要把他放在你sql合适的位置,注意最好不要使用in,这样效率是比较低的。