java
编写的论坛中,
jforum
算是比较多人用的一个,因为有
sso
功能,所以能很好的跟其他系统进行整合。
jforum
还有针对某个版块设置发帖审核的功能,当然,任何一个帖子都要进行审核的话,就缺乏消息的即时性,同时也增加了管理员的负担。
为了符合中国国情,我们在使用
jforum
过程中,可以给它添加一个内容过滤功能。我的实现出发点很简单,在原来审核功能的基础上,针对某一组用户,发现他们发布的内容包含有某些敏感词的时候,把这些内容添加到审核列表中,只有版主和管理员审核后,才显示这些内容。
一、实现分析
一、实现分析
在
jforum-2.1.8
这个版本中,论坛发新帖、回复都是由类
net.jforum.view.forum.
PostAction
来完成的。更具体一点,发表新帖和发表回复都是由
PostAction.
insertSave()
方法实现。发表新帖的时候,会保存一个
Topic
和一个
Post
对象;发表回复的时候,只保存一个
Post
对象。
对于新帖是否要审核,
jforum
是这样判断的:
//
Moderators and admins don't need to have their messages moderated
boolean moderate = (forum.isModerated() &&
! pc.canAccess(SecurityConstants.PERM_MODERATION) &&
! pc.canAccess(SecurityConstants.PERM_ADMINISTRATION));
boolean moderate = (forum.isModerated() &&
! pc.canAccess(SecurityConstants.PERM_MODERATION) &&
! pc.canAccess(SecurityConstants.PERM_ADMINISTRATION));
就是判断发布内容的版块是否需要审核,同时发布内容的用户不是版主或者管理员之类的。然后,对于回复内容,
jforum
是这样判断的:
if (!firstPost && pc.canAccess(SecurityConstants.PERM_REPLY_WITHOUT_MODERATION,
Integer.toString(t.getForumId()))){
moderate = false;
}
Integer.toString(t.getForumId()))){
moderate = false;
}
既判断该用户是否存在回复审核这种权限,如果用户的回复不需要审核,那么
post
对象的
moderate
状态被设置为
false
。最后,
post
对象保存:
//
Save the remaining stuff
p.setModerate(moderate);
int postId = postDao.addNew(p);
p.setModerate(moderate);
int postId = postDao.addNew(p);
二、利用审核状态位添加过滤
我在 post 保存前,再对其内容进行关键字判断(暂时也找不到其他更智能的方法)。
//设置是否被过滤,true说明发布的内容包含了关键字,放到审核列表中
boolean filtered = false;
//如果该组启用了过滤
if(!moderate && pc.canAccess(SecurityConstants.PERM_POST_FILTER)){
ContextFilter cf = ContextFilter.getInstance();
filtered = cf.filter(this.request.getParameter("subject")); //过滤标题
//过滤帖子内容
if(!filtered) {
filtered = cf.filter(p.getText());
}
moderate = moderate || filtered ; //更改审核状态
}
p.setModerate(moderate);
int postId = postDao.addNew(p);
boolean filtered = false;
//如果该组启用了过滤
if(!moderate && pc.canAccess(SecurityConstants.PERM_POST_FILTER)){
ContextFilter cf = ContextFilter.getInstance();
filtered = cf.filter(this.request.getParameter("subject")); //过滤标题
//过滤帖子内容
if(!filtered) {
filtered = cf.filter(p.getText());
}
moderate = moderate || filtered ; //更改审核状态
}
p.setModerate(moderate);
int postId = postDao.addNew(p);
SecurityConstants.PERM_POST_FILTER是我在 SecurityConstants中添加的静态变量:
public
static
final
String PERM_POST_FILTER
=
"
perm_post_filter
"
;
还要给/WEB-INF/config/permissions.xml添加相应的选项,这样就可以针对某一组用户开启内容过滤功能:
<!--
Lock and Unlock topics
-->
< permission id ="perm_moderation_topic_lockUnlock"
title ="Permissions.canLockUnlock" type ="single" >
< option value ="deny" description ="No" />
< option value ="allow" description ="Yes" />
</ permission >
<!-- 内容过滤 -->
< permission id ="perm_post_filter"
title ="Permissions.filterPost" type ="single" >
< option value ="deny" description ="No" />
< option value ="allow" description ="Yes" />
</ permission >
< permission id ="perm_moderation_topic_lockUnlock"
title ="Permissions.canLockUnlock" type ="single" >
< option value ="deny" description ="No" />
< option value ="allow" description ="Yes" />
</ permission >
<!-- 内容过滤 -->
< permission id ="perm_post_filter"
title ="Permissions.filterPost" type ="single" >
< option value ="deny" description ="No" />
< option value ="allow" description ="Yes" />
</ permission >
这样,发布内容的过滤核心代码就完成了。ContextFilter是我自己定义的一个负责内容过滤的类。当然,仅用这段代码的话,发布内容的人在发布了某些包含敏感词的时候,看到的提示信息是,该版块需要审核,请您耐心等待之类的,如果希望告诉用户,他发布的内容含有敏感词的话,需要修改一下waitingModeration()方法。首先看jforum原来重定向到需要审核页面的代码:
else
{
JForumExecutionContext.setRedirect(this.request.getContextPath()
+ "/posts/waitingModeration/"
+ (firstPost ? 0 : t.getId())
+ "/" + t.getForumId()
+ SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION));
}
JForumExecutionContext.setRedirect(this.request.getContextPath()
+ "/posts/waitingModeration/"
+ (firstPost ? 0 : t.getId())
+ "/" + t.getForumId()
+ SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION));
}
我在这基础上添加了一段:
//
内容被过滤了
else
if
(filtered)
{
JForumExecutionContext.setRedirect(this.request.getContextPath()
+ "/posts/waitingModeration/"
+ (firstPost ? 0 : t.getId())
+ "/" + t.getForumId()
+ SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION)+"?filtered=true");
} else {
JForumExecutionContext.setRedirect(this.request.getContextPath()
+ "/posts/waitingModeration/"
+ (firstPost ? 0 : t.getId())
+ "/" + t.getForumId()
+ SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION));
}
JForumExecutionContext.setRedirect(this.request.getContextPath()
+ "/posts/waitingModeration/"
+ (firstPost ? 0 : t.getId())
+ "/" + t.getForumId()
+ SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION)+"?filtered=true");
} else {
JForumExecutionContext.setRedirect(this.request.getContextPath()
+ "/posts/waitingModeration/"
+ (firstPost ? 0 : t.getId())
+ "/" + t.getForumId()
+ SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION));
}
在
waitingModeration()
方法中,给用户的提示信息是这样的:
this
.context.put(
"
message
"
, I18n.getMessage(
"
PostShow.waitingModeration
"
,
new String[] { path + SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION) } ));
new String[] { path + SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION) } ));
可以改成这样:
//
TODO 添加被过滤的说明 BEGIN
if ( this .request.getParameter( " filtered " ) != null ) {
this.context.put("message",
I18n.getMessage("PostShow.filtered.waitingModeration",
new String[] { path +
SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION) }));
} else
// TODO 添加被过滤的说明 END
this .context.put( " message " ,
I18n.getMessage( " PostShow.waitingModeration " ,
new String[] { path +
SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION) } ));
if ( this .request.getParameter( " filtered " ) != null ) {
this.context.put("message",
I18n.getMessage("PostShow.filtered.waitingModeration",
new String[] { path +
SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION) }));
} else
// TODO 添加被过滤的说明 END
this .context.put( " message " ,
I18n.getMessage( " PostShow.waitingModeration " ,
new String[] { path +
SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION) } ));
当然,要在国际化资源文件中添加
PostShow.waitingModeration
这个信息的描述。
以上就能实现对用户发布内容的过滤,当然,用户编辑可以使用类似的方法,但实现起来需要修改的细节就多了很多。