我所在的项目有几十种用户角色,每种用户角色都有不同的权限,所以权限的设计也费了很大心思,最后采取了在webwork(我们项目用的webwork)的Action配置文件里面配置权限。然后用Ant生成权限的数据库脚本,并在数据库中生成权限数据。
Action配置文件的一个Action的权限配置如下:
<action name="showCountyList" class="accountSearchController" method="doNothing" >
<!-- @Label (Show County List) -->
<!-- @Roles(ADMIN,ANALYST,ASSOCIATE_CSR,ASSOCIATE_PROGRAM_SPECIALIST,DOCUMENT_CLERK,RSM:MANAGER,MANAGERS_SUPERVISORS,MANAGER_STAFF) -->
<!-- @Description (Show County List By State Code.) -->
<result name="success" type="freemarker">
/WEB-INF/ftl/account/countyList.html
</result>
</action>
如上所示,这是我们项目中的一个Action, 配置文件中的@Roles()标识的就是哪些Role拥有调用这个Action的权限。这些Role之外的用户调用这个Action的时候就提示Permission Denied页面。
在开发过程中,开发人员根据Use case提供的权限信息来为每个Action配置权限信息。
每次部署系统的时候,配置管理员执行一个Ant target来生成权限的数据库文件,Ant target如下:
<target name="generatePermissionFiles" depends="commonReplaceLogging" description="Generate permission SQL files from configuration data.">
<echo message="Generate Action Access Permissions"/>
<!-- Delete old permission and role permission -->
<delete failοnerrοr="false">
<fileset dir="./gen-src" includes="**/*permission.sql"/>
</delete>
<foreach list="${web.modules}" param="moduleName" target="copyConfigFiles"/>
<java classname="com.psi.vida.portal.webwork.util.ConfigurationParserRunner" fork="true">
<arg value="build/webroot/WEB-INF/classes/xwork.xml"/>
<classpath>
<path refid="test.classpath"/>
</classpath>
<jvmarg value="-Dlog4j.configuration=${basedir}/gen-src/log4j.properties"/>
</java>
<copy tofile="../resource/database/schema/PERMISSION_DATA/permissions.sql" overwrite="true">
<fileset dir="./gen-src" includes="**/permission.sql"/>
</copy>
<copy tofile="../resource/database/schema/PERMISSION_DATA/role_permissions.sql" overwrite="true">
<fileset dir="./gen-src" includes="**/role_permission.sql"/>
</copy>
</target>
如上所示,当执行这个Ant target的时候,Ant会执行一个工具类ConfigurationParserRunner来读取xwork配置文件中的权限配置,然后生成permission.sql和role_permission.sql, 每个Action就是一个权限,保存在permission表里面,每个权限对应一个Role就是Role_permission, 保存在Role_permission表里面。
一下代码是读取权限配置的主要代码:
NodeList actionNodes = pkgEl.getElementsByTagName( "action" );
if ( actionNodes != null && actionNodes.getLength() > 0 ) {
for ( int i = 0; i < actionNodes.getLength(); i++ ) {
Element actionEl = (Element) actionNodes.item( i );
ActionConfig actionConfig = parseAction( actionEl );
pkgConfig.addActionConfig( actionConfig );
if( actionConfig.getUserRoles() == null || actionConfig.getUserRoles().size() == 0 && !actionConfig.isIgnore() ) {
this.printError( "No roles for " + this.currentPackage.getNamespace() + "/" + actionConfig.getName() );
}
this.actions.put( actionConfig.getName(), actionConfig );
}
}
以上代码是读取每个Action配置,取得每个Action的user role. 根据如下的Pattern来进行匹配,代码太多就不贴了。
final static Pattern ROLE_PATTERN = Pattern.compile( ".*@Roles\\s*\\((.+)\\).*" );
以上是权限配置的实现。
当用户进入一个Action的时候,系统会先判断这个用户role是不是拥有这个Action的权限,没有的话就转向到permission denied页面。