【Openfire】网页版的用户注册、登录、修改密码
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】网页版的用户注册、登录、修改密码相关推荐
- 华为服务器如何登录修改密码,服务器登录修改密码
服务器登录修改密码 内容精选 换一换 如果Windows操作系统云服务器未安装密码重置插件,可以参见本节内容重新设置密码.本节操作介绍的方法仅适用于修改Windows本地账户密码,不能修改域账户密码. ...
- pyqt5多界面切换,关联数据库校验,注册登录修改密码操作练习
pyqt5多界面切换,关联数据库校验,注册登录修改密码操作练习import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QWi ...
- 大话手游网页无法链接到服务器,大话西游手游网页版IE不能登录 IE无法登录解决办法...
大话西游手游网页版IE浏览器怎么登录?大话西游手游网页版IE不能登录怎么办?下面小编就为大家分享大话西游手游网页版IE无法登录解决办法,一起来看看吧! 目前,大话西游手游网页版无法在以下版本的IE浏览 ...
- 智能管家App kotlin版(3)——用户注册/登录/忘记重置密码/个人数据编辑开发
前言:Bmob后端云为我们用户操作带来了极大的便捷,本文章主要是涵盖了一个用户系统逻辑,实现用户的登录,注册,找回密码,修改密码,邮箱验证,以及记住密码等功能的实现,通过本章你可以学习到宝贵的用户操作 ...
- python+selenium 爬取微博(网页版)并解决账号密码登录、短信验证
使用python+selenium 爬取微博 前言 为什么爬网页版微博 为什么使用selenium 怎么模拟微博登录 一.事前准备 二.Selenium安装 关于selenium 安装步骤 三.sel ...
- html+css+php+mysql实现注册+登录+修改密码(附完整代码)
注:转载及使用源代码请注明来源!如疑问可私信! 目的:在利用QT软件进行登录软件开发时,就想要实现点击按钮跳转到指定网页进行注册以及修改密码等操作,就像QQ客户端那样可以实现网页端修改密码,申请账户等 ...
- php实现简单的用户注册,登录,修改个人信息接口
1. 连接数据库 数据库名为eating, user表用于存放用户的信息 //connect_mysql.php <?php header("Content-type:text/htm ...
- Windows域控 批量设置用户下次登录 修改密码【全域策略生效】
目录 需求:为了安全要求,要求域控中所有用户,在下次登录之后,必须强制修改密码
- [微信] 微信网页版扫码登录的实现
我们先来回顾一下微信网页版的扫码登录过程 1. 打开微信网页版,https://wx.qq.com/ 2. 打开手机微信客户端,扫一扫 3. 点击确定,登录 看似简单的操作流程,中间涉及的数据交互有很 ...
最新文章
- 圣诞大战!于嘉可以不要这么偏见吗
- WebServices 简介
- 【两种方法】基础实验4-2.7 修理牧场 (25 分)
- Educational Codeforces Round 37 (Rated for Div. 2) E. Connected Components? 暴力 + 补图的遍历
- 华为cor—al10_cor al10是华为什么型号 cor al10是华为啥型号
- 机器学习速成课程 | 练习 | Google Development——编程练习:Pandas 简介
- PHP合并大文件 高性能 低内存 低CPU 快速合并大文件 非耗时操作 快速合并PDF等影视大文件...
- ax3000 梅林_用梅林午餐肉十分钟就能做出来的美食,超级美味又健康,午餐肉还是要选择中粮!...
- 机器学习实战 Tricks —— 训练数据均值标准差标准化测试样本
- html读取json换行无效,前端Json换行显示
- 《计算机网络基础》考试大纲
- go mysql_build-web-application-with-golang
- 机电工程系计算机网络技术,我院物联网工程专业3+1及计算机网络技术专业2+1项目正式开营...
- 2016年计算机网络考研真题及解析
- 光明顶短信支付:格式详解
- 为什么硬件工程师招聘如此之难?
- 天心阁吉他神秘人专访
- 证件照蓝底变白底的方法
- 深度学习方法的超分辨率(Super-resolution)方向论文【不定期更新】
- 开源的驰骋工作流程引擎,工作流程管理系统,表结构与运行机制。