Openfire客户端的开发是借助Smack提供的方法。Smack可以从官网下载。如果是Openfire3.7.1的版本,建议使用Smack3.2.2与其匹配。官网地址:http://www.igniterealtime.org/downloadServlet?filename=smack/smack_3_2_2.zip

下载之后解压,将里面的4个jar复制到网络工程WEB-INF下的lib文件夹,这样,即可以使用smack的api进行开发。

目标是做出如下样子的工程,在网页版提供用户注册、登录和密码修改的功能。

网络工程的目录结构如下:

web.xml,没什么好说的,仅仅是一些简单的struts2配置,没有其它任何的内容。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"version="2.4"><filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class></filter><filter-mapping><filter-name>struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping>
</web-app>  

DB.java这是在《【Java】利用单例模式、可变参数优化Java操作Mysql数据库、JDBC代码的写作》( 点击打开链接)我已经详细说明过的工具类,这里不再多说了。

package tool;import java.sql.*;
import java.util.*;  public class DB {  // 一、单例初始化连接  private Connection con;  // 以下代码,保证该类只能有一个实例  private DB() {  try {  Class.forName("com.mysql.jdbc.Driver");  // 其中test是我们要链接的数据库,user是数据库用户名,password是数据库密码。  // 3306是mysql的端口号,一般是这个  // 后面那串长长的参数是为了防止乱码,免去每次都需要在任何语句都加入一条SET NAMES UTF8  String url = "jdbc:mysql://localhost:3306/openfire?useUnicode=true&characterEncoding=utf8&useOldAliasMetadataBehavior=true";  String user = "root";  String password = "root";  con = DriverManager.getConnection(url, user, password);  } catch (Exception e) {  e.printStackTrace();  }  } // 私有无参构造方法  // 在自己内部定义自己的一个实例,只供内部调用  private static DB db = null;  // 这个类必须自动向整个系统提供这个实例对象  // 这里提供了一个供外部访问本class的静态方法,可以直接访问  public static DB getInstance() {  if (db == null) {  db = new DB();  }  return db;  }  // 二、查询  // 使用SQL查询,查询的结果是一个结果集(视图)  public List<Object[]> getBySql(String sql) {  List<Object[]> result_list = new ArrayList<Object[]>();  try {  PreparedStatement ps = con.prepareStatement(sql);  ResultSet rs = ps.executeQuery();  while (rs.next()) {  ResultSetMetaData md = rs.getMetaData();  int columnCount = md.getColumnCount();  Object[] row_data_set = new Object[columnCount];  for (int i = 1; i <= columnCount; i++) {  row_data_set[i - 1] = rs.getObject(i);  }  result_list.add(row_data_set);  }  return result_list;  } catch (SQLException e) {  e.printStackTrace();  return null;  }  }  // 查询sql语句带参数的情况  public List<Object[]> getBySql(String sql, Object[] param) {  List<Object[]> result_list = new ArrayList<Object[]>();  try {  PreparedStatement ps = con.prepareStatement(sql);  for (int i = 0; i < param.length; i++) {  ps.setObject(i + 1, param[i]);  }  ResultSet rs = ps.executeQuery();  while (rs.next()) {  ResultSetMetaData md = rs.getMetaData();  int columnCount = md.getColumnCount();  Object[] row_data_set = new Object[columnCount];  for (int i = 1; i <= columnCount; i++) {  row_data_set[i - 1] = rs.getObject(i);  }  result_list.add(row_data_set);  }  return result_list;  } catch (SQLException e) {  e.printStackTrace();  return null;  }  }  // 使用SQL查询,查询的结果是唯一  public Object getBySql_result_unique(String sql) {  try {  PreparedStatement ps = con.prepareStatement(sql);  ResultSet rs = ps.executeQuery();  rs.next();  return rs.getObject(1);  } catch (SQLException e) {  e.printStackTrace();  return null;  }  }  // 查询sql语句带参数的情况  public Object getBySql_result_unique(String sql, Object[] param) {  try {  PreparedStatement ps = con.prepareStatement(sql);  for (int i = 0; i < param.length; i++) {  ps.setObject(i + 1, param[i]);  }  ResultSet rs = ps.executeQuery();  rs.next();  return rs.getObject(1);  } catch (SQLException e) {  e.printStackTrace();  return null;  }  }  // 三、增删改  // insert、update、delete等修改数据库的语句  public void setBySql(String sql) {  try {  PreparedStatement ps = con.prepareStatement(sql);  ps.executeUpdate();  } catch (SQLException e) {  e.printStackTrace();  }  }  // sql语句带参数的情况  public void setBySql(String sql, Object[] param) {  try {  PreparedStatement ps = con.prepareStatement(sql);  for (int i = 0; i < param.length; i++) {  ps.setObject(i + 1, param[i]);  }  ps.executeUpdate();  } catch (SQLException e) {  e.printStackTrace();  }  }  // 析构函数,中断数据库的连接  protected void finalize() throws Exception {  if (!con.isClosed() || con != null) {  con.close();  }  }  }  

index.jsp也就是如上的效果截图,布局很简单,就三个表单指向相应action,<%@ page isELIgnored="false"%>是为了保证EL表达式,能够在Tomcat5.5使用。

<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<%@ page isELIgnored="false"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>index</title>
</head>
<body>${msg}<hr><p>用户注册<br><form method="post" action="register">用户名:<input type="text" name="username" /><br>密码:<input type="password" name="password" /><br><input type="submit" value="注册" /></form></p><hr><p>用户登录<br><form method="post" action="login">用户名:<input type="text" name="username" /><br>密码:<input type="password" name="password" /><br><input type="submit" value="登录" /></form></p><hr><p>修改密码<br><form method="post" action="modify_password">用户名:<input type="text" name="username" /><br>旧密码:<input type="password" name="password" /><br>新密码:<input type="password" name="newpassword" /><br><input type="submit" value="修改" /></form></p>
</body>
</html>

chat.jsp是用户成功登录,所跳转的页面,很简单。

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>聊天</title>
</head>
<body>欢迎,${sessionScope.username},<a href="logout">登出</a>
</body>
</html>

核心关键在于两个,一个是从Openfire源代码中拷贝过来的Blowfish.java,这个文件的详细说明请看《【Openfire】验证用户输入密码是否正确》( 点击打开链接)。

这个文件很长,修改的地方,主要是里面关于org.slf4j记录日志的信息的注释掉,然后是对其42-53行的构造方法进行修改,这样以后用到就不用每次都要写代码,在数据库中查询ofproperty中passwordKey所对应的值。修改之后如下:

public Blowfish() {// 改过// hash down the password to a 160bit keyDB db = DB.getInstance();String password = (String) db.getBySql_result_unique("select propValue from ofproperty where name='passwordKey'");MessageDigest digest = null;try {digest = MessageDigest.getInstance("SHA1");digest.update(password.getBytes());} catch (Exception e) {// Log.error(e.getMessage(), e);}// setup the encryptor (use a dummy IV)m_bfish = new BlowfishCBC(digest.digest(), 0);digest.reset();
}

最后,所有核心方法都在test.user这个类中。对照struts.xml所配的action:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts><package name="test" extends="struts-default"><action name="register" class="test.user" method="register"><result name="success" type="redirect">/index.jsp</result></action><action name="login" class="test.user" method="login"><result name="success" type="redirect">/chat.jsp</result><result name="input" type="redirect">/index.jsp</result></action><action name="logout" class="test.user" method="logout"><result name="success" type="redirect">/index.jsp</result></action><action name="modify_password" class="test.user" method="modify_password"><result name="success" type="redirect">/index.jsp</result></action></package>
</struts>   

这个user.java的代码如下:

package test;import java.util.Map;import org.jivesoftware.smack.AccountManager;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;import tool.Blowfish;
import tool.DB;import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;public class user extends ActionSupport {private static final long serialVersionUID = 5570391705428296402L;private String username;private String password;private String newpassword;private String msg;// 判断输入的密码是否与数据库密码一致private boolean checkPassword(String username, String password) {Blowfish blowfish = new Blowfish();DB db = DB.getInstance();String db_password = (String) db.getBySql_result_unique("select encryptedPassword from ofuser where username=?",new Object[] { username });if (blowfish.decryptString(db_password).equals(password)) {return true;} else {return false;}}// 用户注册public String register() throws XMPPException {DB db = DB.getInstance();if (username.length() == 0) {msg = "用户名不得为空!";return SUCCESS;}if (db.getBySql("select * from ofuser where username=?",new Object[] { username }).size() > 0) {msg = "该用户名已经存在!";} else {ConnectionConfiguration config = new ConnectionConfiguration("127.0.0.1", 5222);Connection connection = new XMPPConnection(config);connection.connect();AccountManager amgr = connection.getAccountManager();amgr.createAccount(username, password);// 会自动使用Openfire的Blowfish编码加密密码。msg = "注册成功!";System.out.println("新用户注册:" + username + ",密码:" + password);connection.disconnect();}return SUCCESS;}// 用户登录public String login() throws XMPPException {if (checkPassword(username, password)) {msg = "登录成功!";ConnectionConfiguration config = new ConnectionConfiguration("127.0.0.1", 5222);Connection connection = new XMPPConnection(config);connection.connect();connection.login(username, password);Map session = ActionContext.getContext().getSession();session.put("username", username);session.put("connection", connection);return SUCCESS;} else {msg = "密码错误!";return INPUT;}}// 用户登出public String logout() {Map session = ActionContext.getContext().getSession();Connection connection = (Connection) session.get("connection");connection.disconnect();session.clear();return SUCCESS;}// 修改密码public String modify_password() throws XMPPException {if (checkPassword(username, password)) {ConnectionConfiguration config = new ConnectionConfiguration("127.0.0.1", 5222);Connection connection = new XMPPConnection(config);connection.connect();connection.login(username, password);// 登录之后才能修改密码connection.getAccountManager().changePassword(newpassword);System.out.println("用户:" + username + ",修改密码从:" + password + ",变为:"+ newpassword);connection.disconnect();msg = "修改成功!";} else {msg = "密码错误!";}return SUCCESS;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getNewpassword() {return newpassword;}public void setNewpassword(String newpassword) {this.newpassword = newpassword;}}

注册、登录、修改密码本来没有什么好说的,因为smack已经提供了一定量的api。

但是,由于smack并没有提供判断用户所输入密码是否正确的方法,只能自己手动到数据库,再配合Blowfish算法查询。如果密码是不正确的,直接利用connect.login方法的话,会直接报错,导致这个网络工程崩溃,try和catch也是没用的。所以在connect.login之前,需要自己查询用户输入的密码是否正确。

再有一点是,如果用户登录正确,那么这个connect对象就应该压入session,跟着他所登录的用户名一起走,为后续的聊天和加好友操作的提供依据,也就是以后的所有动作,最简单就是上面代码的登录,都要使用这个connection来操作,而不是自己再new一个。

【Openfire】网页版的用户注册、登录、修改密码相关推荐

  1. 华为服务器如何登录修改密码,服务器登录修改密码

    服务器登录修改密码 内容精选 换一换 如果Windows操作系统云服务器未安装密码重置插件,可以参见本节内容重新设置密码.本节操作介绍的方法仅适用于修改Windows本地账户密码,不能修改域账户密码. ...

  2. pyqt5多界面切换,关联数据库校验,注册登录修改密码操作练习

    pyqt5多界面切换,关联数据库校验,注册登录修改密码操作练习import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QWi ...

  3. 大话手游网页无法链接到服务器,大话西游手游网页版IE不能登录 IE无法登录解决办法...

    大话西游手游网页版IE浏览器怎么登录?大话西游手游网页版IE不能登录怎么办?下面小编就为大家分享大话西游手游网页版IE无法登录解决办法,一起来看看吧! 目前,大话西游手游网页版无法在以下版本的IE浏览 ...

  4. 智能管家App kotlin版(3)——用户注册/登录/忘记重置密码/个人数据编辑开发

    前言:Bmob后端云为我们用户操作带来了极大的便捷,本文章主要是涵盖了一个用户系统逻辑,实现用户的登录,注册,找回密码,修改密码,邮箱验证,以及记住密码等功能的实现,通过本章你可以学习到宝贵的用户操作 ...

  5. python+selenium 爬取微博(网页版)并解决账号密码登录、短信验证

    使用python+selenium 爬取微博 前言 为什么爬网页版微博 为什么使用selenium 怎么模拟微博登录 一.事前准备 二.Selenium安装 关于selenium 安装步骤 三.sel ...

  6. html+css+php+mysql实现注册+登录+修改密码(附完整代码)

    注:转载及使用源代码请注明来源!如疑问可私信! 目的:在利用QT软件进行登录软件开发时,就想要实现点击按钮跳转到指定网页进行注册以及修改密码等操作,就像QQ客户端那样可以实现网页端修改密码,申请账户等 ...

  7. php实现简单的用户注册,登录,修改个人信息接口

    1. 连接数据库 数据库名为eating, user表用于存放用户的信息 //connect_mysql.php <?php header("Content-type:text/htm ...

  8. Windows域控 批量设置用户下次登录 修改密码【全域策略生效】

    目录 需求:为了安全要求,要求域控中所有用户,在下次登录之后,必须强制修改密码

  9. [微信] 微信网页版扫码登录的实现

    我们先来回顾一下微信网页版的扫码登录过程 1. 打开微信网页版,https://wx.qq.com/ 2. 打开手机微信客户端,扫一扫 3. 点击确定,登录 看似简单的操作流程,中间涉及的数据交互有很 ...

最新文章

  1. 圣诞大战!于嘉可以不要这么偏见吗
  2. WebServices 简介
  3. 【两种方法】基础实验4-2.7 修理牧场 (25 分)
  4. Educational Codeforces Round 37 (Rated for Div. 2) E. Connected Components? 暴力 + 补图的遍历
  5. 华为cor—al10_cor al10是华为什么型号 cor al10是华为啥型号
  6. 机器学习速成课程 | 练习 | Google Development——编程练习:Pandas 简介
  7. PHP合并大文件 高性能 低内存 低CPU 快速合并大文件 非耗时操作 快速合并PDF等影视大文件...
  8. ax3000 梅林_用梅林午餐肉十分钟就能做出来的美食,超级美味又健康,午餐肉还是要选择中粮!...
  9. 机器学习实战 Tricks —— 训练数据均值标准差标准化测试样本
  10. html读取json换行无效,前端Json换行显示
  11. 《计算机网络基础》考试大纲
  12. go mysql_build-web-application-with-golang
  13. 机电工程系计算机网络技术,我院物联网工程专业3+1及计算机网络技术专业2+1项目正式开营...
  14. 2016年计算机网络考研真题及解析
  15. 光明顶短信支付:格式详解
  16. 为什么硬件工程师招聘如此之难?
  17. 天心阁吉他神秘人专访
  18. 证件照蓝底变白底的方法
  19. 深度学习方法的超分辨率(Super-resolution)方向论文【不定期更新】
  20. 开源的驰骋工作流程引擎,工作流程管理系统,表结构与运行机制。

热门文章

  1. 虚拟华尔街的最新资讯 虚拟经济体的最新经济体
  2. MyEclipse全局搜索
  3. 软件测试详解17--接口对接
  4. 计算机二级系统班C语言讲义,计算机二级C语言2017辅导讲义:C语言基本知识
  5. javascript 微信企业号APP应用URL转换成PC端可正常访问的URL
  6. Modbus RTU笔记总结
  7. Unity3D--加载界面、开始界面
  8. java告警_错误日志告警实战
  9. java io 设备未就绪,GRADLE遇见“设备未就绪”
  10. ERP咨询顾问必备的七种公关能力