并发型服务器

博客展示的登录系统的服务器端,将实现重复型服务器。

Client–server model

客户端-服务器模型(Client–server model)简称C/S结构,是一种网络架构。大部分网络应用程序在编写时都假设一端是客户,另一端是服务器,其目的是为了让服务器为客户提供一些特定的服务。可以将这种服务分为两种类型:重复型或并发型。重复型服务器通过以下步骤进行交互:

等待一个客户请求的到来。

处理客户请求。

发送响应给发送请求的客户。

返回第 1 步。

并发型服务器采用以下步骤:

等待一个客户请求的到来。

启动一个新的服务器来处理这个客户的请求。在这期间可能生成一个新的进程、任务或线程,并依赖底层操作系统的支持。这个步骤如何进行取决于操作系统。生成的新服务器对客户的全部请求进行处理。处理结束后,终止这个新服务器。

返回第 1 步。

并发服务器的优点在于利用多线程来处理客户的请求,如果操作系统允许多任务,那么就可以同时为多个客户服务,本博客将实现并发型服务器。

Request/Response model

请求/响应(Request/Response)模型一种通用的网络模型架构,该模型下永远都由客户端发起请求,由服务器进行响应并发送回响应报文。如果没有客户端进行请求或曾经请求过,那么服务器是无法将消息推送到客户端的。

三层架构

本系统将基于三层架构实现,由表示层、逻辑层和存储层 3 层组成。表示层是应用的最高层,负责与用户进行交互,并将通信信息发送给逻辑层。逻辑层执行细节处理来控制应用的功能,连接到存储层。存储层则往往是数据库,用于检索并维护数据。

表示层向逻辑层发送请求,逻辑层对存储层完成检索和更新数据等操作,最后逻辑层根据存储层的数据对表示层进行响应。从概念上看,三层架构是一种线性关系。

登录系统设计

登录系统由客户端和服务器 2 个部分组成。

客户端

客户端需要接收用户输入的用户名和密码,然后将这 2 个信息发送给服务器。发送完毕之后等待服务器的响应信息,若在一定的时间内收到了服务器的响应,并且响应“操作成功”,则完成用户的登录操作。除了支持用户的登录操作,客户端还应该支持其他基于用户的操作,例如注册用户、密码修改和注销用户等。

修改密码和注销用户的操作,不能在登录前被调用,只能在登录之后。

服务器

无论客户端是否启动,服务器应当保持启动的状态,并且持续监听分配给服务器的端口。当服务器收到客户端发送的数据时,服务器对数据进行处理并执行对应的操作。根据服务器的执行情况,若操作成功则向客户端通告操作成功,否则通告失败,接着继续 监听客户端发送的数据。

数据库连接

用户名和密码信息将保存在数据库中,当服务器接收到客户端的数据时,将按照客户端请求的操作与数据库进行交互。根据客户端请求的方式不同,服务器与数据库交互时需要执行的操作为:

用户请求

数据库操作

注册

INSERT INTO

登录

SELECT

密码修改

UPDATE

用户注销

DELETE

客户端实现

UserBehaviorDAO 接口

由于客户端和服务器的交互方式不仅仅只有三层架构的实现方式,还可以实现多层架构等其他方式。此时服务器及其它层的动作对于客户端来说是不可见的,因此定义 UserBehaviorDAO 接口支持客户端和服务器的交互方式的更换。

/**

* UserBehaviorDAO 接口指定了针对用户的行为

* @author 乌漆WhiteMoon

* @version 1.0

*/

public interface UserBehaviorDAO {

/**

* 这个方法将实现用户的注册操作

* @param username 用户名,String

* @param password 密码,String

* @return 操作是否成功,boolean

*/

public static boolean registerUser(String username, String password) {

return false;

}

/**

* 这个方法将实现用户的改密码操作

* @param username 用户名,String

* @param password 密码,String

* @param new_password 新密码,String

* @return 操作是否成功,boolean

*/

public static boolean changePassword(String username, String password, String new_password) {

return false;

}

/**

* 这个方法将实现用户的登录操作

* @param username 用户名,String

* @param password 密码,String

* @return 操作是否成功,boolean

*/

public static boolean signIn(String username, String password) {

return false;

}

/**

* 这个方法将实现用户的销户操作

* @param username 用户名,String

* @param password 密码,String

* @return 操作是否成功,boolean

*/

public static boolean cancelUser(String username,String password) {

return false;

}

}

UserBehavior 类

UserBehavior 类是静态类,实现了 UserBehaviorDAO 接口,该类的 4 个方法将把数据传输给套接字进行和服务器的通信。

服务器实现

UserDao 类

由于服务器需要与数据库进行交互,而数据库应该作为一个可替换组件存在,因此定义 UserDao 接口指定了与数据库的交互行为。

/**

* SqlActionDao 接口指定了与数据库的交互行为

* @author 乌漆WhiteMoon

* @version 1.0

*/

public interface UserDao {

/**

* 查找用户名是否已存在,用户注册时用

* @param username 被查找的用户名

* @return true为用户名不存在,false为用户名已存在

* @throws SQLException 数据库异常

*/

public static boolean selectUsername(String username) throws SQLException{

return false;

}

/**

* 核对用户名和密码是否存在且匹配,用户登录和其他增删改操作时使用

* @param username 用户名

* @param password 密码

* @return true为用户名和密码存在且匹配,false为用户名或密码错误

* @throws SQLException 数据库异常

*/

public static boolean checkUser(String username, String password) throws SQLException{

return false;

}

/**

* 向数据库插入一个uesr记录,注册操作时用,调用该方法前应使用selectUsername()方法检查

* @param username 用户名

* @param password 密码

* @return true为记录插入成功,false为插入失败

* @throws SQLException 数据库异常

*/

public static boolean insertUser(String username, String password) throws SQLException{

return false;

}

/**

* 删除一条记录,注销用户时用,调用该方法前应使用checkUser()方法检查

* @param username 用户名

* @return true为删除成功,false删除失败

* @throws SQLException 数据库异常

*/

public static boolean deleteUser(String username) throws SQLException{

return false;

}

/**

* 更新一个uesr的password字段,改密码操作时用,调用该方法前应使用checkUser()方法检查

* @param username 用户名

* @param new_password 新密码,用于替换原有的条目

* @return true为更换成功,false更换失败

* @throws SQLException 数据库异常

*/

public static boolean updateUserPasswd(String username, String new_password) throws SQLException{

return false;

}

}

UserImpl 类

UserImpl 类是静态类,实现了 UserDao 接口,该类将连接到 MySQL 数据库进行对数据的操作。为了支持对数据库的连接,还需要 MysqlConnect 类完成连接操作。

数据封装

操作码和分隔符

客户端发送的有效载荷为一个字符串,该字符串由操作码、用户名和密码 3 个部分组成,3 个部分之间用 “+” 连接。

服务器接收到数据之后,将数据按照分隔符 “+” 进行分割。

//分割明文,执行对应的操作

String result_set[] = result_decode.split("+");

通过操作码执行对应的操作,操作码和用户的请求的关系如下:

用户请求

数据库操作

1

注册

2

登录

3

密码修改

4

用户注销

改密码操作还需要传输新密码,因此“密码”部分的内容为 “password '+' newpassword”。

数据加密

MD5Util 类

MD5Util 类只有 getMD5Str() 方法,用于对传入的字符串进行 MD5 加密。MD5Util 类会被 UserBehavior 类调用,传输的用户名和密码都会进行 MD5 加密,从而保证这 2 者的安全性。

例如对用户名“张三”和密码“123456”调用 getMD5Str() 方法进行加密,输出结果为:

615db57aa314529aaa0fbe95b3e95bd3

e10adc3949ba59abbe56e057f20f883e

服务器的日志文件如下所示:

Base 64 加密

即使对用户名和密码进行加密,攻击者仍然可能截取密文进行提交,为了保证安全性需要对整个有效载荷进行加密。UserClient 类的 sendRequest 方法使用 base64 加密,加密的代码为:

//明文写入操作码,跟着用户名即密码

String Plaintext = actionCode + " " + username + " " + password;

//对明文进行 base64加密

String ciphertext = Base64.getEncoder().encodeToString(Plaintext.getBytes("utf-8"));

Base 64 解密

服务器接收到数据之后要先对数据进行 Base 64 解密,解密的代码如下:

DataInputStream in = new DataInputStream(server.getInputStream());

//将客户端传来的密文转成明文

String result_decode = new String(Base64.getDecoder().decode(in.readUTF()));

MySQL 数据库

users 表

数据库中的 users 表用于存储 MD5 加密后的用户名和密码,users 表的字段有。

下图是存储了 3 个用户信息的 users 表。

SQL 查询语句

selectUsername() 方法

这个方法将基于select查找用户名是否已存在,用户注册时用。

SELECT username FROM users WHERE binary username = '%s';

checkUser() 方法

这个方法将基于 select 核对用户名和密码是否存在且匹配,用户登录和其他增删改操作时使用.

SELECT username,password FROM users WHERE binary username = '%s' AND password = '%s';

insertUser() 方法

这个方法将基于 insert 向数据库插入一个 uesr 记录,注册操作时用,调用该方法前应使用

selectUsername() 方法检查。

INSERT INTO users(username, password) values('%s','%s');

deleteUser() 方法

这个方法将基于 delete 删除一条记录,注销用户时用,调用该方法前应使用 checkUser() 方法检查。

"DELETE FROM users WHERE username = '%s';"

updateUserPasswd() 方法

这个方法将基于 update 向更新一个 uesr 的 password 字段,改密码操作时用,调用该方法前应使用 checkUser() 方法检查。

UPDATE users SET password='%s' WHERE username = '%s';

Socket 实现

Socket

不同端系统的进程是通过彼此之间向套接字发送报文来实现通信,套接字就好比是门禁,想要和应用程序进行通信需要先通过门禁的验证。同理也不是什么报文都能随意出门的,必须是得到允许的报文才会被送出门去。

为了连接主机,我们需要目标主机的 IP 地址,这样才能知道要发给哪个端系统,就像送信就一定要有收件人。但是由于一台主机上可能运行着好多个进程,需要指定一个端口号,令指定的进程接收分组。需要强调的是,我们自己写的端口需要避开 RFC 定义的协议,例如 HTTP 协议的端口号 80。

Client-Socket

UserClient 类

UserClient 类是基于请求响应模型的客户端套接字,该类应该在客户端被调用,只有 sendRequest() 发送报文一个方法。

Server-Socket

Response 类

本类的方法将接受套接字收到的数据,调用 SqlActionDao 接口执行对客户端请求的操作,操作完成后进行响应。

UserServer 类

UserServer 类将继承 Thread 类,run() 方法将保持对分配给该进程的端口的监听,若接收到数据则调用 Response 类中的方法进行操作。

Customer 类

用户登录之后,将会把登录的用户信息实例化一个 Customer 类。注意 Customer 类不会保存用户的密码,安全的做法是让用户执行改密码和注销操作时都额外提供一次密码。

public class Customer {

private final String username;

private final String username_md5;

private LinkedList Inbox; //收件箱

private LinkedList Outbox; //发件箱

/**

* 这个方法是customer对象的构造器

* @param username 用户名,String

* @return customer对象

*/

public Customer(String username) {

this.username = username;

this.username_md5 = MD5Util.getMD5Str(username);

}

}

GUI 设计

登录界面

注册用户界面

密码修改界面

销户界面

参考资料

《计算机网络(第七版)》 谢希仁 著,电子工业出版社

《TCP/IP 详解 卷1:协议》[美]W.Richard Stevens 著,范建华 胥光辉 张涛 等译,谢希仁 校,机械工业出版社

《SQL注入攻击与防御(第2版)》 [美]Justin Clarke 著,施宏斌 叶愫 译,清华大学出版社

计算机网络:协议栈分层

应用层:HTTP 协议

HTTP请求/响应模型

Java DAO 模式

应用层:UDP 套接字编程

应用层:TCP 套接字编程

MySQL——SELECT

MySQL——增、删、改

java 登陆系统设计_Java 程序设计——登录系统相关推荐

  1. 基于Java实现简易的 注册 + 登录 系统 (中级)

    引言 :这个项目我以学习的角度进行补充和完善,力求把登录 + 注册做到最完美!!! 该项目适用于 学习完 基础的编程语法的同学进行进阶学习 [1]基于Java实现简易的 注册 + 登录 系统 非 数据 ...

  2. cas java单点登录_java单点登录系统CAS的简单使用

    http://blog.csdn.net/yunye114105/article/details/7997041 参考: http://blog.csdn.net/diyagea/article/de ...

  3. java sso单点登录源码_Java单点登录系统 sso源码下载

    这是一个使用Java开发的单点登陆系统(sso). 运行截图 单点登陆介绍 单点登录,这就是我们通常称之为SSO.一般来说,大型系统平台将使用这些东西.它解决了频繁登录和验证的过程,即用户的一次登录被 ...

  4. JS+Java项目实战(1)--学生登录系统开发

    文章目录 0. 前置条件 1. 任务背景 2. 任务目标 3. 相关知识点 4. 任务实操 4.1 创建Java Web项目 4.2 使用VSCode打开项目编辑前端页面 4.3 开发前端页面 4.4 ...

  5. java模拟登陆系统_Java模拟登录系统抓取内容【转载】

    1 @Component2 public class Login extendsBaseJobs {3 4 SimpleDateFormat sdf = new SimpleDateFormat(&q ...

  6. 签到考勤java课设_Java程序设计课程设计学生考勤系统Word版

    <Java程序设计课程设计学生考勤系统Word版>由会员分享,可在线阅读,更多相关<Java程序设计课程设计学生考勤系统Word版(6页珍藏版)>请在人人文库网上搜索. 1.传 ...

  7. 教材订购模块java代码实现_java教材征订系统

    每天记录学习,每天会有好心情.*^_^* 今天将为大家分析一个基于web的java教材征订系统,因此本系统选择学校的教材征订为研究对象,以实现教材征订网络化管理.提高工作效率.减少教材征订中的错误为目 ...

  8. 猜数字java程序设计分析_JAVA程序设计课程设计-猜数字游戏设计

    JAVA程序设计课程设计-猜数字游戏设计 课 程 设 计 报 告课程设计名称 Java 程序设计 专 业 计算机科学与技术 班 级 2 班 学 号 08030212 姓 名 指导教师 成 绩 2011 ...

  9. java对嵌入式_Java用于嵌入式系统的优点

    Java用于嵌入式系统的优点 与个人计算机这样的通用计算机系统不同,嵌入式系统通常执行的是带有特定要求的预先定义的任务.yjbys小编下面为你整理了关于Java用于嵌入式系统的优点,希望对你有所帮助. ...

最新文章

  1. HDU - 2767 Proving Equivalences tanjar强连通-DAG性质
  2. bzoj4592[SHOI2015]脑洞治疗仪
  3. UWP 推荐 - 限时免费的RSS阅读器《RSS 追踪》登录 Windows 10
  4. AlertDialog创建6种对话框的用法
  5. TensorFlow for Hackers - Part II
  6. 理解 ActivityExecutionContextManager
  7. HDU - 4687 Boke and Tsukkomi(一般图最大匹配-带花图)
  8. ORACLE初始化参数文件详细文档
  9. notebook python 内嵌 数据库_python数据分析:在jupyter notebook上使用pythonSQL做数据分析...
  10. asp连oracle测试,ASP连接Oracle
  11. 欧姆字符的编码c语言,《编码:隐匿在计算机软硬件背后的语言》读书笔记
  12. css 图片反色,颜色反色,高斯模糊
  13. truncate table(截断表)
  14. xmind 7 pro破解补丁|xmind 7 pro注册机下载(附xmind7 pro序列号/注册码/激活码)
  15. 轮换对称性实质 和差化积公式之sinθ+cosθ推导 rd原理,二重积分坐标系转化为什么多了个r; 二重积分几何意义: 二重积分物理意义: 二重积分求导:
  16. 装完docker电脑黑屏无法启动_教你电脑启动后黑屏该怎么办
  17. 计算机启动突然断电,电脑启动运行过程主机突然断电怎么办
  18. 【机器人栅格地图】基于灰狼算法求解栅格地图路径规划及避障含Matlab源码
  19. PHP源码加密,以前只知道zend guard,今天才知道,原来还有个 ioncube
  20. 【Java就业培训教材】——集合的学习

热门文章

  1. java图片亮度调整
  2. 网件rax40可以刷梅林_支持WiFi6,带宽达到3000Mbps,网件RAX40路由器评测 | 钛极客...
  3. Know your weapons Ⅱ
  4. 跟我一起了解less(3):判断和循环
  5. 推荐几个精致的web UI框架
  6. 深入理解计算机系统(2.4)---C语言的有符号与无符号、二进制整数的扩展与截断...
  7. [杂谈] 2013年新目标
  8. [原创] 图片操作的类(ImageLibrary)-按比例缩放图片
  9. [转载] Python内置函数-min函数和max函数-详解
  10. [转载] PYTHON 字符串转换为二进制字符串,二进制字符串转换为字符串