JForum做为一个成熟的开源BBS论坛解决方案,提供了非常方便的SSO集成接口。它的主页上和网上都有许多介绍如何用SSO方式进行集成的办法。这里不罗列,google可以找到许多资料,主要描述一下如何解决用户名重名的一种方式。目前使用的JForum版本是2.1.8
简单地介绍一下采用的SSO方式。由于应用上需要一个BBS,找了JForum做为一个子系统,集成到现成的一个管理系统当中,管理系统本身有一套完全的身份权限认证方案,由于系统的安全要求不是特别严格,所以采了最直接和最省事的方式:Cookie写入。即在管理系统登录时,把用户信息写入Cookie,JForum从Cookie中读取用户信息进行登录。
为JForum项目添加一个SSO接口的扩展类CookieSSO,主要实现authenticateUser(RequestContext request)方法。方法大体如下:
按照正常的方式就是从管理系统把一个用户的username传过来。然后在这里取出,return给调用方法进行验证。在实际项目中,问题就出在这里了!
举例说有二个用户名字都叫:李四,那么当二个李四都同时登录时,JForum的验证方式就会出问题!它认不清到底是哪个李四,数据库查询时只按第一个来!
仔细看一下jforum的数据库表设计,jforum_user这个表没有display_user_name类似的字段,它就是把username做为显示在页面上的用户名,如果不做集成,把它单独做为一个BBS时,username既是登录的用户名,也是显示在页面上的用户名。主要原因我想大概就是老外的思维方式跟中国人的不太一样。中国人登录的时候用英文,显示的时候还有一个昵称或是中文名等。
所以把它集成的时候,用Cookie传送一个username给JForum时就得用中文(而且重名的概率很大)。我们再跟进一个它的代码,看是谁调用了SSO接口的这个方法:
结果发现是类:net.jforum.ControllerUtils的checkSSO(UserSession userSession)方法
解决的思路:修改JForum的数据库表,并更改代码和页面文件是不科学的,工作量大,而且风险比较高!那么就继续把username用来保存中文名称,它的user_id是一个自增的数字序列。在管理系统的用户表中,扩展一个字段bbs_user_id,用来保存在JForum中的用户id,这个字段就肯定是唯一的,在管理系统登录时,把这个bbs_user_id查询出来,放到Cookie中。在JForum验证时,不再使用它推荐的返回username方式,而是返回它的user_id值。
那么回到最上面的CookieSSO类的代码,这里返回的String其实是jforum_user表中user_id字段。为了匹配,那么net.jforum.ControllerUtils的checkSSO(UserSession userSession)方法也要改!改为下面的方式:
这样就可以解决认证的问题!同时又保证username可以是中文的,而且重名也无所谓。
附加:查看它的SQL配置文件,发现有selectUserByName这样的方法,通过用户名来查找用户,起初怕是它在某些模块中使用了。后来详细查看,发现它只使用在后台管理(即admin模块)中的用户管理。这个页面提供了一个按用户名来查找用户的功能,所以也是非常合理的!
刚进场的时候戏就落幕
简单地介绍一下采用的SSO方式。由于应用上需要一个BBS,找了JForum做为一个子系统,集成到现成的一个管理系统当中,管理系统本身有一套完全的身份权限认证方案,由于系统的安全要求不是特别严格,所以采了最直接和最省事的方式:Cookie写入。即在管理系统登录时,把用户信息写入Cookie,JForum从Cookie中读取用户信息进行登录。
为JForum项目添加一个SSO接口的扩展类CookieSSO,主要实现authenticateUser(RequestContext request)方法。方法大体如下:
public String authenticateUser(RequestContext request) {
String userId = null;
Cookie c = ControllerUtils.getCookie("ehrbbsuserid");
if(c!=null){
userId = c.getValue();
}
logger.info("单点登录BBS用户ID为:" + userId);
return userId;
}
就是从Cookie中读取在管理系统中放入的username。但是这里写的是:ehrbbsuserid,主要是这个变量名来区分传过来的内容的不同。String userId = null;
Cookie c = ControllerUtils.getCookie("ehrbbsuserid");
if(c!=null){
userId = c.getValue();
}
logger.info("单点登录BBS用户ID为:" + userId);
return userId;
}
按照正常的方式就是从管理系统把一个用户的username传过来。然后在这里取出,return给调用方法进行验证。在实际项目中,问题就出在这里了!
举例说有二个用户名字都叫:李四,那么当二个李四都同时登录时,JForum的验证方式就会出问题!它认不清到底是哪个李四,数据库查询时只按第一个来!
仔细看一下jforum的数据库表设计,jforum_user这个表没有display_user_name类似的字段,它就是把username做为显示在页面上的用户名,如果不做集成,把它单独做为一个BBS时,username既是登录的用户名,也是显示在页面上的用户名。主要原因我想大概就是老外的思维方式跟中国人的不太一样。中国人登录的时候用英文,显示的时候还有一个昵称或是中文名等。
所以把它集成的时候,用Cookie传送一个username给JForum时就得用中文(而且重名的概率很大)。我们再跟进一个它的代码,看是谁调用了SSO接口的这个方法:
结果发现是类:net.jforum.ControllerUtils的checkSSO(UserSession userSession)方法
/**
* Checks for user authentication using some SSO implementation
* @param userSession UserSession
*/
protected void checkSSO(UserSession userSession)
{
try {
SSO sso = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();
String username = sso.authenticateUser(JForumExecutionContext.getRequest());
if (username == null || username.trim().equals("")) {
userSession.makeAnonymous();
}
else {
SSOUtils utils = new SSOUtils();
if (!utils.userExists(username)) {
SessionContext session = JForumExecutionContext.getRequest().getSessionContext();
String email = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_EMAIL_ATTRIBUTE));
String password = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_PASSWORD_ATTRIBUTE));
if (email == null) {
email = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_EMAIL);
}
if (password == null) {
password = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_PASSWORD);
}
utils.register(password, email);
}
this.configureUserSession(userSession, utils.getUser());
}
}
catch (Exception e) {
e.printStackTrace();
throw new ForumException("Error while executing SSO actions: " + e);
}
}
在这里明显的,它是通过username去确定这个人是否存在?再继续跟进代码就会发现最后调用了Dao的selectUserByName方法。* Checks for user authentication using some SSO implementation
* @param userSession UserSession
*/
protected void checkSSO(UserSession userSession)
{
try {
SSO sso = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();
String username = sso.authenticateUser(JForumExecutionContext.getRequest());
if (username == null || username.trim().equals("")) {
userSession.makeAnonymous();
}
else {
SSOUtils utils = new SSOUtils();
if (!utils.userExists(username)) {
SessionContext session = JForumExecutionContext.getRequest().getSessionContext();
String email = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_EMAIL_ATTRIBUTE));
String password = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_PASSWORD_ATTRIBUTE));
if (email == null) {
email = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_EMAIL);
}
if (password == null) {
password = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_PASSWORD);
}
utils.register(password, email);
}
this.configureUserSession(userSession, utils.getUser());
}
}
catch (Exception e) {
e.printStackTrace();
throw new ForumException("Error while executing SSO actions: " + e);
}
}
解决的思路:修改JForum的数据库表,并更改代码和页面文件是不科学的,工作量大,而且风险比较高!那么就继续把username用来保存中文名称,它的user_id是一个自增的数字序列。在管理系统的用户表中,扩展一个字段bbs_user_id,用来保存在JForum中的用户id,这个字段就肯定是唯一的,在管理系统登录时,把这个bbs_user_id查询出来,放到Cookie中。在JForum验证时,不再使用它推荐的返回username方式,而是返回它的user_id值。
那么回到最上面的CookieSSO类的代码,这里返回的String其实是jforum_user表中user_id字段。为了匹配,那么net.jforum.ControllerUtils的checkSSO(UserSession userSession)方法也要改!改为下面的方式:
protected void checkSSO(UserSession userSession)
{
try {
SSO sso = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();
String username = sso.authenticateUser(JForumExecutionContext.getRequest());
if (username == null || username.trim().equals("")) {
userSession.makeAnonymous();
}
else {
// SSOUtils utils = new SSOUtils();
/* 重构为按userId验证身份 */
// if (!utils.userExists(username)) {
// SessionContext session = JForumExecutionContext.getRequest().getSessionContext();
//
// String email = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_EMAIL_ATTRIBUTE));
// String password = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_PASSWORD_ATTRIBUTE));
//
// if (email == null) {
// email = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_EMAIL);
// }
//
// if (password == null) {
// password = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_PASSWORD);
// }
//
// utils.register(password, email);
// }
/* 新添加的代码 */
UserDAO dao = DataAccessDriver.getInstance().newUserDAO();
User user = dao.selectById(Integer.parseInt(username));
// this.configureUserSession(userSession, utils.getUser());
this.configureUserSession(userSession, user);
}
}
catch (Exception e) {
e.printStackTrace();
throw new ForumException("Error while executing SSO actions: " + e);
}
}
{
try {
SSO sso = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();
String username = sso.authenticateUser(JForumExecutionContext.getRequest());
if (username == null || username.trim().equals("")) {
userSession.makeAnonymous();
}
else {
// SSOUtils utils = new SSOUtils();
/* 重构为按userId验证身份 */
// if (!utils.userExists(username)) {
// SessionContext session = JForumExecutionContext.getRequest().getSessionContext();
//
// String email = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_EMAIL_ATTRIBUTE));
// String password = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_PASSWORD_ATTRIBUTE));
//
// if (email == null) {
// email = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_EMAIL);
// }
//
// if (password == null) {
// password = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_PASSWORD);
// }
//
// utils.register(password, email);
// }
/* 新添加的代码 */
UserDAO dao = DataAccessDriver.getInstance().newUserDAO();
User user = dao.selectById(Integer.parseInt(username));
// this.configureUserSession(userSession, utils.getUser());
this.configureUserSession(userSession, user);
}
}
catch (Exception e) {
e.printStackTrace();
throw new ForumException("Error while executing SSO actions: " + e);
}
}
这样就可以解决认证的问题!同时又保证username可以是中文的,而且重名也无所谓。
附加:查看它的SQL配置文件,发现有selectUserByName这样的方法,通过用户名来查找用户,起初怕是它在某些模块中使用了。后来详细查看,发现它只使用在后台管理(即admin模块)中的用户管理。这个页面提供了一个按用户名来查找用户的功能,所以也是非常合理的!
刚进场的时候戏就落幕
相关推荐
综上所述,JForum 2.1.6 是一个强大的论坛解决方案,其开源特性和MVC设计模式使其成为开发者理想的论坛构建工具。通过深入理解其源码,开发者可以充分利用JForum的潜力,构建出满足特定需求的高效论坛系统。
Personally think is the best forum for the Java source code, open source, you can watch the official website of the latest developments http://www.jforum.net/
JForum,一个知名的开源论坛系统,以其高效、可扩展性和丰富的功能在互联网上广受欢迎。2.1.8 版本的源码发布,为我们提供了一个深入了解其内部工作原理的机会。本文将主要围绕JForum 2.1.8的源码进行解析,探讨其...
在这个"jforum-2.1.8-编译代码.zip"压缩包中,包含了JForum 2.1.8版本的源代码,对于开发者来说,这是一个深入理解JForum工作原理、进行二次开发或定制化改造的宝贵资源。 首先,让我们了解JForum的基本架构。...
总结来说,Jforum-2.1.9是一个强大且灵活的论坛解决方案,结合MyEclipse的强大开发工具,能够为开发者提供一个高效的开发环境。无论你是想搭建一个社区网站,还是希望深入学习Java Web开发,Jforum都是一个值得研究...
JForum 2.1.4 版本是这个项目的其中一个稳定版本,提供了许多改进和优化,使得它在众多的Java论坛解决方案中脱颖而出。 **1. JForum 的核心特性** - **多语言支持**:JForum 支持多种语言,用户可以根据需求选择...
**JForum-2.1.4.rar_JForum-2.1.4_jforum_jsp_jsp_struts_struts** 这个压缩包文件包含了一个基于JSP和Struts框架的论坛系统——JForum的2.1.4版本。JForum是一款开源的、基于Java技术的讨论论坛软件,它提供了强大...
2.启动tomcat, 访问如:http://172.18.20.164:8080/install.jsp,设置相关参数,此是在WEB-INF/config下会生成jforum-custom.conf配置文件。 为了解决中文问题修改了WebRequestContext.java类。 第149行,default....
这个压缩包“jforum-2.5.0安装包+安装方式.rar”包含了JForum 2.5.0版本的安装文件和相关的安装指南,主要文件为“jforum-2.5.0.war”,这是一个Web应用的归档文件,可以直接部署在支持Servlet和JSP的Web服务器上。...
无论是对Java Web开发感兴趣的初学者,还是寻求提升论坛系统解决方案的专业开发者,都能从中受益匪浅。如果你在研究过程中遇到任何问题或有进一步交流的意向,可以联系发布者zlf112zlf@163.com,共同探讨JForum的...
从网上下了很多jforum-2.1.9都是无法进入主题,此资源是从GitHub获取的源码重新编译打包,实测可用
jforum-2.1.8 jar包.zipjforum-2.1.8 jar包.zipjforum-2.1.8 jar包.zipjforum-2.1.8 jar包.zipjforum-2.1.8 jar包.zipjforum-2.1.8 jar包.zip
JForum是一款基于Java技术的开源讨论论坛系统,它采用JavaServer Pages(JSP)技术进行开发,并结合了Servlet和JavaBean,提供了高效、可扩展的论坛解决方案。版本2.1.9是该系统的稳定版本,其源码的开放性为开发者...
JForum是一个功能强大的、基于Java的开源讨论论坛系统,它提供了丰富的社区管理工具和用户交互功能,深受开发者和社区管理员的喜爱。本篇文章将深入探讨JForum 2.1.8版本,特别是其Web工程版的特点和在Eclipse环境下...
Java论坛,测试人员进入性能,自动化测试练习很好的项目。 搭建环境:Tomcat,JDK,Mysql 版本:jforum-2.7.0.war,需要搭建的环境版本比较高,我的是Tomcat,JDK,Mysql 都是8.0以上的版本
jforum-2.1.8版本完整源代码(1),因为完整版本超过15mb,因此分成两部分下载。
**Java论坛系统 JForum...总的来说,Java论坛系统 JForum是一个功能齐全、安全可靠的社区解决方案,适合需要建立在线讨论平台的组织和个人。通过不断迭代和更新,JForum持续优化用户体验,满足日益增长的社区互动需求。
文件名称列表中的"jforum-2.1.9"表示这是JForum的2.1.9版本。每个版本都会包含一系列的改进和修复,确保系统的稳定性和安全性。在部署JForum时,我们需要下载对应的版本,并按照官方文档的指导进行安装和配置。 ...