系统详细设计过程指南

  • Post author:
  • Post category:其他




引言



为规范研发团队的详细设计过程,提高设计质量与设计输出能力,特编制此文档。

设计过程


为便于理解系统设计的整个过程,本文选取最为常见的用户登录认证的需求为示例,通过该需求的设计过程中的每一步,设计人员可对整个设计过程的方法和工具有深入全面的理解。




需求示例:



  1. 系统应采用口令、验证码组合的鉴别技术对用户进行身份鉴别,身份标识具有唯一性,密码采用不可逆算法加密加盐存储。

  2. 系统应具有登录失败处理功能,应配置限制非法登录次数等措施,登录失败次数超过一定的次数,系统将自动锁定用户,锁定用户一定时间后方可继续登录。


需求

分析

识别业务用例



发现参与者



涉众:也称为干系人,是与要建设的系统有利益相关的一切人和事,涉众的利益要求会影响系统的建设。只要和这个系统有利益关系的都是这个项目的涉众。


参与者:是涉众的代表,对系统的要求直接影响系统的建设,他们的要求就是系统需求的来源。参与者通过对系统提出要求来获得他所代表的涉众的利益。


可通过以下两个问题来识别参与者:


  • 谁对系统有着明确的目标和要求并且主动发出动作?

  • 系统为谁服务?



识别业务用例



用例(Use Case)是把现实世界的需求捕获下来的方法。用例定义了一组用例实例,其中每个实例都是系统所执行的一系列操作。


一个完整的用例定义由参与者、前置条件、场景、后置条件构成。


用例的特征:


  • 用例是相对独立的。

  • 一个用例就是一个需求单元、分析单元、设计单元、开发单元、测试单元。

  • 用例必然是以动宾短语形式出现的。

  • 这件事必须由一个参与者发起。

  • 用例执行结果对参与者来说是可观测的和有意义的。




示例:





在该需求中,用户所有的活动都集中在登录认证的活动中,所以登录认证作为本需求的业务用例。我们就可以画出如下用例图:


对于用例图中无法表示的内容,可以通过用例规约进行详细说明,以上用例的用例规约如下:

用例名称:


用户登录认证

简要说明:

用户访问系统登录页,通过口令及验证码登录的过

事件流:

基本事件流:


  1. 用户

    打开登录页面。

  2. 用户

    输入正确的用户名和密码。

  3. 用户

    输入正确的验证码。

  4. 用户

    提交登录请求。

  5. 系统

    校验用户输入的验证码。

  6. 系统


    校验用户输入的用户名和密码。

  7. 系统


    将用户状态标记为“已登录”。

  8. 系统


    查询用户功能权限。

  9. 系统


    显示用户功能界面。

扩展事件流:

  1. 如果用户输入的验证码不匹配,则提示“验证码不正确”。
  2. 如果用户名和密码不匹配,则提示“登录名或登录密码不正确”。
  3. 如果登录失败次数超过一定的次数,则系统锁定自动锁定该用户,锁定一定时间后才可继续登录,锁定期间用户登录则提示“您登录失败超过X次,请Y分钟后重试”。其中X次和Y分钟可配置。

非功能需求:

前置条件

后置条件

a)如果用户输入正确的用户名、密码、验证码,则登录成功。

b)如果用户输入的用户名、密码、验证码之一不正确,则登录失败。

c)如果用户连续X次登录失败,则系统锁定用户。锁定一定时间后才可继续登录。


说明:


以上示例中仅包含一个业务主角和一个业务用例,在我们实际的需求中,通常都会有多个业务主角和多个业务用例,设计人员在需求分析时,可按照如上方法,找出所有的业务主角,针对每一个业务主角识别出该业务主角所有的业务用例。

识别关键业务用例



什么是关键需求:


关键的功能需求,即涉及的模块最多、最典型的功能,或必须实现的重要的功能。


关键的质量属性需求,是那些经过权衡取舍、最终决定重点支持的质量属性需求。


关键的商业需求。




示例:



由于本次需求仅登录认证一个业务用例,是必须实现功能,所以登录用例作为本次需求的关键用例。


说明:


对于多业务主角、多业务用例的场景,设计人员需要认真评估哪些业务主角的哪些用例是关键用例,输出关键用例的列表。

关键业务用例分析


关键用例的分析方法有很多,主要工具有时序图、协作图、鲁棒图等。


时序图用于描述按时间顺序排列的对象之间的交互模式。


图 登录认证时序图


使用鲁棒图对关键用例进行分析


图 认证用例实现初稿


以上是认证登录用例的实现初稿,初步看上去,好像没什么问题,但是仔细分析一下,却发现还有一些细节没有体现出来,比如验证码返回前端的不是数字,而应该是图片,未考虑登录失败处理,未考虑登录凭证等。


于是,我们对上述鲁棒图进行了调整,调整后的如下:


调整后的实现


上图还存在一个问题,就是失败处理在这里没有体现具体的细节,如需要判断失败次数是否超过阈值,如果是,则锁定用户,否则返回相应的错误信息。用户被锁定后,在什么节点进行解锁判断,也需要考虑。但由于鲁棒图不太擅长表现此类复杂场景,可换做流程图(泳道图)表现更合适。


通过完成后的鲁棒图,可识别出一系列页面、动作和实体,这些将成为下一步工作的重要输入。

领域建模


所谓领域(Domain),即是对现实世界问题的一种统称,是一个组织的业务开展方式,体现一个组织所做的事情以及其中所包含的一切业务范围和所进行的活动,我们在开发软件时面对的就是组织的领域。例如,一个电商网站的领域包含了产品名录、订单、库存和物流的概念,而医疗信息化公司关注挂号、就诊、用药、健康报告等领域。




示例:



通过上面用例分析步骤中,我们识别出了一系列实体:用户、登录日志、会话、验证码,这些就可以看做领域实体,实体关系图如下:


领域模型


实体关系图中需要表现出实体间的关系,用户与会话是一对多的关系,用户与登录日志也是一对多的关系,验证码中无用户信息。但是验证码需要存储在会话中以确保下次请求时,系统能够找回验证码。


如果用例中涉及到了状态的变化,就需要通过状态图来表现状态之间的转换规则,本用例涉及到账户的未登录、登录、锁定、登录失败等状态的转换,所以需要通过状态图表示出来,状态图如下:


状态图表示领域模型

系统设计

技术关注点


这里列出技术上需要进行预研、技术上比较有难度或重要性比较高的的关注点,并通过预研最终确定技术选型。




示例



  1. 认证

  1. 密码采用不可逆算法加密加盐存储。

  2. 随机验证码转换成为图片,且图片需具备一定的混淆能力。


解决方案


  1. 密码通存储采用不可逆的加密算法(


    MD5





    + S    alt


    ,使用方法如


    MD5(username+password+Salt)





    其中


    Salt


    为随机字符串,并妥善保存。

  2. 采用


    java.awt


    包实现验证码图片。

  3. 会话管理

  4. 系统需有专门的模块对会话进行管理,包括会话创建、存储、销毁、会话超时等控制。


技术分析


当前业界常用的安全框架有


Spring Security





jwt





Shiro


等,各自优缺点如下:



Spring Security


Spring Security


是一个能够为基于


Spring


的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在


Spring


应用上下文中配置的


Bean


,充分利用了


Spring IoC


(控制反转),


DI





依赖注入)和


AOP


(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。它是一个轻量级的安全框架,它确保基于


Spring


的应用程序提供身份验证和授权支持。它与


Spring MVC


有很好地集成,并配备了流行的安全算法实现捆绑在一起。安全主要包括两个操作“认证”与“验证”(有时候也会叫做权限控制)。“认证”是为用户建立一个其声明的角色的过程,这个角色可以一个用户、一个设备或者一个系统。“验证”指的是一个用户在你的应用中能够执行某个操作。在到达授权判断之前,角色已经在身份认证过程中建立了。



JWT


JWT


又名


Json Web Token


,基于数字签名,定义了一个紧凑、字包含的方式,用于


json


在各方之间安全传输信息。


使用场景


一般用于授权认证和数据交换:


Authorization (


授权


) :


这是使用


JWT


的最常见场景。一旦用户登录,后续每个请求都将包含


JWT


,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的


JWT


的一个特性,因为它的开销很小,并且可以轻松地跨域使用


Information Exchange (


信息交换


) :


对于安全的在各方之间传输信息而言,


JSON Web Tokens


无疑是一种很好的方式。因为


JWTs


可以被签名,例如,用公钥


/


私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。



Shiro


Apache Shiro





Java


的一个安全框架,在轻量级的程序应用更广泛,简化了


Spring security


的功能,提供了处理身份认证,授权,企业会话管理和加密的功能。


应用领域


  • 验证用户

  • 对用户执行访问控制,如:

  • 判断用户是否拥有角色


    admin




  • 判断用户是否拥有访问的权限

  • 在任何环境下使用


    Session API


    。例如


    CS


    程序。

  • 可以使用多个用户数据源。例如一个是


    oracle


    用户库,另外一个是


    mysql


    用户库。

  • 单点登录(


    SSO


    )功能。




  • Remember Me


    ”服务


    ,类似购物车的功能,


    shiro


    官方建议开启


核心领域:


  • 身份验证


    Authentication


    (重要模块)

  • 授权


    Authorization


    (重要模块)

  • 会话管理


    Session Management


    (重要模块)

  • 加密


    Cryptography


    (重要模块)

  • web support





    Web


    支持,可以非常容易的集成到


    Web


    环境


    (


    次要


    )

  • Caching


    :缓存,比如用户登录后,其用户信息、拥有的角色


    /


    权限不必每次去查,这样可以提高效率;


    (


    次要


    )

  • Concurrency





    shiro


    支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;


    (


    次要


    )

  • Testing


    :提供测试支持;


    (


    次要


    )

  • Run As


    :允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;


    (


    次要


    )

  • Remember Me


    :记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了


    (


    次要


    )


框架


优点


缺点


Spring Security


与Spring集成度较好


配置相对比较难懂


Shiro


shiro


配置更加容易理解,容易上手。


shiro


不仅仅可以使用在web中,它可以工作在任何应用环境中。


在集群会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。


Shiro


提供的密码加密使用起来非常方便。


传统的sessionId的方式存储在server端,占用server端的资源。


jwt


token


存放在客户端,减轻服务器端的负担,可以

让负载均衡器将用户传递到任意服务器。


每次请求都需要带上token,没有会话,安全性大。


解决方案


  1. 经过综合考虑,采用


    Shiro


    安全框架对会话进行管理比较适合当前的技术框架。

组件设计

组件划分


回顾我们在用例分析、领域建模的输出(页面、操作、实体),这些将会成为组件划分的依据之一,组件划分的另一依据是对技术关注点细化的结果。




示例



我们在关键用例分析中识别以下内容:


页面:登录页、首页。


操作:生成验证码、生成验证码图片、保存验证码、返回验证码、校验验证码、读取验证码、校验用户密码、失败处理、获取用户信息、生成会话、准备首页数据。


实体:验证码、登录日志、用户、会话。


我们在技术关注点中识别出了MD5加密、会话管理等。


分析过程:


1.


页面部分如何划分,取决于后台模块如何划分。所以我们先分析后端的模块。


2.


几个验证码相关的操作(生成验证码、生成验证码图片、保存验证码、读取验证码)可合并为一个模块,其中生成验证码图片可以放在验证码模块中,也可以拆分出通用的模块,取决于系统中是否有此类的复用要求。这里我们将生成验证码图片独立出来成为通用模块,所以我们识别出了两个模块:验证码处理、数字转图片。


3.


校验验证码、校验用户密码、失败处理、生成会话等几个操作都是为登录服务的,离开登录而独立存在就没有意义,所以这几个可以合并成登录模块。


4.


准备首页数据这个操作和业务有关,包含一系列的操作,也不是本用例的主要关注点,所以在未能看清的情况下,可设置首页模块。


5.MD5


加密作为通用模块,会话管理采用Shiro,可作为单独的模块。


根据以上的分析,登录页面可纳入登录模块,首页页面可纳入到首页模块。


经过以上分析我们划分了一下模块:


  • 登录控制:包括校验验证码、校验用户密码、失败处理、生成会话、登录页面。

  • 验证码处理:包括生成验证码、验证码转图片、保存验证码、读取验证码。

  • 会话管理:创建会话、获取会话、销毁会话。

  • 首页:准备首页数据、首页页面。

  • 数字转图片

  • 加密处理


接下来我们还需要对这些模块进行分类,使其归属到不同的子系统或上层组件中。


登录控制、验证码处理、会话管理在逻辑上都是和登录相关的,所以这几个可以合并到一个上层组件中。


首页控制涉及到业务,不在本次设计重点,单独放置在一个上层组件中。


数字转图片、加密处理等属于通用功能,所以可以放在上层的通用组件中,组件图如下:




图 组件图

组件协作




示例



图 组件协作图

组件设计


图 登录控制组件

类设计


类名

LoginController


包路径

com.design.sample.security.web.controller


方法列表


说明

login

处理用户登录请求

checkCaptcha

校验验证码

checkAccountPassword

校验用户名密码

createSession

创建Session

handleFail

失败处理

checkLockedAccount

校验账户是否处于锁定状态

lockAccount

锁定账户

unlockAccount

解锁账户


方法

public User login(String account, String password, String captchaCode)


参数


含义


出、入参类型


说明

account

账号

入参

password

密码

入参

captchaCode

验证码

入参


处理逻辑

  1. 参数合法性校验(非空、格式)。
  2. checkCaptcha()校验验证码,如果失败,则调用handleFailed()进行失败处理。
  3. checkAccountPassword()校验用户名,密码,如果失败,则调用handleFailed()进行失败处理。
  4. checkLock()判断用户是否处于锁定状态。
  5. unlockAccount()解锁用户。
  6. createSession()创建会话。
  7. 返回用户对象。


方法

private Boolean checkCaptcha(String captchaCode)


参数


含义


出、入参类型


说明

captchaCode

验证码

入参


处理逻辑

  1. sessionManager.getSession()获取session。
  2. 从session中获取验证码code。
  3. 校验验证码code是否匹配。
  4. 如果匹配成功则返回true。
  5. 如果匹配失败则返回false。


方法

private Boolean checkAccountPassword(String account, String password)


参数


含义


出、入参类型


说明

account

账号

入参

password

密码

入参


处理逻辑

  1. 查找账号=account的用户信息。
  2. 如果不存在用户信息,返回false。
  3. 如果存在用户信息,则:

将password按照加密规则加密,将加密后的字串与用户信息中的password字段进行比较,如果匹配返回true,否则返回false。


方法

private Boolean createSession(String account, String password)


参数


含义


出、入参类型


说明

account

账号

入参

password

密码

入参


处理逻辑

  1. 查找账号=account的用户信息。
  2. 如果不存在用户信息,返回false。
  3. 如果存在用户信息,则:

将password按照加密规则加密,将加密后的字串与用户信息中的password字段进行比较,如果匹配返回true,否则返回false。


方法

private String handleFail(User user)


参数


含义


出、入参类型


说明

account

账号

入参

password

密码

入参


处理逻辑

  1. 如果user为null,则不做处理,正常返回。
  2. 记录登录日志,记录失败次数。
  3. 判断失败次数是否超过阈值:

如果超过阈值,则将用户设置为锁定状态,记录锁定时间,返回错误消息“登录失败超过X次,用户已锁定,请Y分钟后重试”。


方法

private Boolean checkLockedAccount(User user)


参数


含义


出、入参类型


说明

user

用户信息

入参


处理逻辑

  1. 判断用户是否处于锁定状态。
  2. 如果用户处于锁定状态,且锁定时间未过期,则返回true,否则返回false。


方法

private void lockAccount(User user)


参数


含义


出、入参类型


说明

user

用户信息

入参


处理逻辑

  1. 修改用户信息状态为锁定。
  2. 记录锁定时间。


方法

private Boolean unlockAccount(User user)


参数


含义


出、入参类型


说明

user

用户信息

入参


处理逻辑

  1. 将用户信息状态设置为未登录。


图 验证码处理组件


类名

CaptchaGenerater


包路径

com.design.sample.security.captcha


方法列表


说明

createCaptcha

创建验证码

gnenrateCaptchaCode

生成验证码code

codeToImage

将验证码code转换成图片


图 会话管理


类名

SessionManager


包路径

com.design.sample.security.session


方法列表


说明

createSession

创建session

getSession

获得本地session

removeSession

销毁session


图 数字转图片


类名

CaptchaImage


包路径

com.design.sample.common.tools


方法列表


说明

codeToImage

将code转换为图片


方法

public static BufferImage codeToImage(String code)


参数


含义


出、入参类型


说明

code

待转换的code

入参


处理逻辑


图 加密处理


类名

EncryptUtil


包路径

com.design.sample.common.tools


方法列表


说明

encryptMd5

md5编码


方法

public static String encryptMd5(String content)


参数


含义


出、入参类型


说明

content

加密内容

入参


处理逻辑

实体设计


图 实体关系图

实体类


类名

User


包路径

com.design.sample.security.entity


属性列表


说明

String id

id

String name

名称

String password

密码

String account

账号

Integer sex

性别

String mobile

手机号码

Date birthday

出生日期

User createUser

创建用户

Timestamp createTime

创建时间

Timestamp modifyTime

修改时间

Integer status

状态


类名

LoginLog


包路径

com.design.sample.security.entity


属性列表


说明

String id

id

String account

账号

Timestamp loginTime

登录时间

Integer loginStatus

登录状态

数据库设计


用户表


tbl_user


属性


code


属性名称


类型


长度


说明

id

id

character varying

name

名称

character varying

password

密码

character varying

account

账号

character varying

sex

性别

character(1)

mobile

手机号码

character(11)

birthday

出生日期

Date

create_user

创建用户

character varying

create_time

创建时间

Timestamp

modify_time

修改时间

Timestamp

status

状态

Integer

0 正常

1 锁定

2 注销

主键字段

id

索引列表

索引名称

USER_UIDX_ACCOUNT

索引类型

唯一索引

索引字段

account

索引名称

USER_IDX_NAME

索引类型

普通索引

索引字段

name


登录日志表


tbl_login_log


属性


code


属性名称


类型


长度


说明

id

id

character varying

account

账号

character varying

login_time

登录时间

Timestamp

login_status

登录状态

Integer

0 成功

1 失败

主键字段

id

索引列表

索引名称

LOGIN_LOG_IDX_ACCOUNT

索引类型

普通索引

索引字段

account, login_time



版权声明:本文为jiangbb8686原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。