赞
踩
为规范研发团队的详细设计过程,提高设计质量与设计输出能力,特编制此文档。
为便于理解系统设计的整个过程,本文选取最为常见的用户登录认证的需求为示例,通过该需求的设计过程中的每一步,设计人员可对整个设计过程的方法和工具有深入全面的理解。
需求示例:
涉众:也称为干系人,是与要建设的系统有利益相关的一切人和事,涉众的利益要求会影响系统的建设。只要和这个系统有利益关系的都是这个项目的涉众。
参与者:是涉众的代表,对系统的要求直接影响系统的建设,他们的要求就是系统需求的来源。参与者通过对系统提出要求来获得他所代表的涉众的利益。可通过以下两个问题来识别参与者:
用例(Use Case)是把现实世界的需求捕获下来的方法。用例定义了一组用例实例,其中每个实例都是系统所执行的一系列操作。
一个完整的用例定义由参与者、前置条件、场景、后置条件构成。
用例的特征:
示例:
在该需求中,用户所有的活动都集中在登录认证的活动中,所以登录认证作为本需求的业务用例。我们就可以画出如下用例图:
对于用例图中无法表示的内容,可以通过用例规约进行详细说明,以上用例的用例规约如下:
用例名称: 用户登录认证
简要说明: 用户访问系统登录页,通过口令及验证码登录的过
事件流: 基本事件流:
扩展事件流:
非功能需求: 前置条件 无 后置条件 a)如果用户输入正确的用户名、密码、验证码,则登录成功。 b)如果用户输入的用户名、密码、验证码之一不正确,则登录失败。 c)如果用户连续X次登录失败,则系统锁定用户。锁定一定时间后才可继续登录。 |
说明:
以上示例中仅包含一个业务主角和一个业务用例,在我们实际的需求中,通常都会有多个业务主角和多个业务用例,设计人员在需求分析时,可按照如上方法,找出所有的业务主角,针对每一个业务主角识别出该业务主角所有的业务用例。
什么是关键需求:
关键的功能需求,即涉及的模块最多、最典型的功能,或必须实现的重要的功能。
关键的质量属性需求,是那些经过权衡取舍、最终决定重点支持的质量属性需求。
关键的商业需求。
示例:
由于本次需求仅登录认证一个业务用例,是必须实现功能,所以登录用例作为本次需求的关键用例。
说明:
对于多业务主角、多业务用例的场景,设计人员需要认真评估哪些业务主角的哪些用例是关键用例,输出关键用例的列表。
关键业务用例分析
关键用例的分析方法有很多,主要工具有时序图、协作图、鲁棒图等。
时序图用于描述按时间顺序排列的对象之间的交互模式。
图 登录认证时序图
使用鲁棒图对关键用例进行分析
图 认证用例实现初稿
以上是认证登录用例的实现初稿,初步看上去,好像没什么问题,但是仔细分析一下,却发现还有一些细节没有体现出来,比如验证码返回前端的不是数字,而应该是图片,未考虑登录失败处理,未考虑登录凭证等。
于是,我们对上述鲁棒图进行了调整,调整后的如下:
调整后的实现
上图还存在一个问题,就是失败处理在这里没有体现具体的细节,如需要判断失败次数是否超过阈值,如果是,则锁定用户,否则返回相应的错误信息。用户被锁定后,在什么节点进行解锁判断,也需要考虑。但由于鲁棒图不太擅长表现此类复杂场景,可换做流程图(泳道图)表现更合适。
通过完成后的鲁棒图,可识别出一系列页面、动作和实体,这些将成为下一步工作的重要输入。
领域建模
所谓领域(Domain),即是对现实世界问题的一种统称,是一个组织的业务开展方式,体现一个组织所做的事情以及其中所包含的一切业务范围和所进行的活动,我们在开发软件时面对的就是组织的领域。例如,一个电商网站的领域包含了产品名录、订单、库存和物流的概念,而医疗信息化公司关注挂号、就诊、用药、健康报告等领域。
示例:
通过上面用例分析步骤中,我们识别出了一系列实体:用户、登录日志、会话、验证码,这些就可以看做领域实体,实体关系图如下:
领域模型
实体关系图中需要表现出实体间的关系,用户与会话是一对多的关系,用户与登录日志也是一对多的关系,验证码中无用户信息。但是验证码需要存储在会话中以确保下次请求时,系统能够找回验证码。
如果用例中涉及到了状态的变化,就需要通过状态图来表现状态之间的转换规则,本用例涉及到账户的未登录、登录、锁定、登录失败等状态的转换,所以需要通过状态图表示出来,状态图如下:
状态图表示领域模型
这里列出技术上需要进行预研、技术上比较有难度或重要性比较高的的关注点,并通过预研最终确定技术选型。
示例
解决方案
技术分析
当前业界常用的安全框架有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的功能,提供了处理身份认证,授权,企业会话管理和加密的功能。
应用领域
核心领域:
框架 | 优点 | 缺点 |
Spring Security | 与Spring集成度较好 | 配置相对比较难懂 |
Shiro | shiro配置更加容易理解,容易上手。 shiro 不仅仅可以使用在web中,它可以工作在任何应用环境中。 在集群会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。 Shiro提供的密码加密使用起来非常方便。 | 传统的sessionId的方式存储在server端,占用server端的资源。 |
jwt | token存放在客户端,减轻服务器端的负担,可以让负载均衡器将用户传递到任意服务器。 每次请求都需要带上token,没有会话,安全性大。 |
|
解决方案
回顾我们在用例分析、领域建模的输出(页面、操作、实体),这些将会成为组件划分的依据之一,组件划分的另一依据是对技术关注点细化的结果。
示例
我们在关键用例分析中识别以下内容:
页面:登录页、首页。
操作:生成验证码、生成验证码图片、保存验证码、返回验证码、校验验证码、读取验证码、校验用户密码、失败处理、获取用户信息、生成会话、准备首页数据。
实体:验证码、登录日志、用户、会话。
我们在技术关注点中识别出了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 | 验证码 | 入参 |
|
处理逻辑 | |||
|
方法 | private Boolean checkCaptcha(String captchaCode) | ||
参数 | 含义 | 出、入参类型 | 说明 |
captchaCode | 验证码 | 入参 |
|
处理逻辑 | |||
|
方法 | private Boolean checkAccountPassword(String account, String password) | ||
参数 | 含义 | 出、入参类型 | 说明 |
account | 账号 | 入参 |
|
password | 密码 | 入参 |
|
处理逻辑 | |||
将password按照加密规则加密,将加密后的字串与用户信息中的password字段进行比较,如果匹配返回true,否则返回false。 |
方法 | private Boolean createSession(String account, String password) | ||
参数 | 含义 | 出、入参类型 | 说明 |
account | 账号 | 入参 |
|
password | 密码 | 入参 |
|
处理逻辑 | |||
将password按照加密规则加密,将加密后的字串与用户信息中的password字段进行比较,如果匹配返回true,否则返回false。 |
方法 | private String handleFail(User user) | ||
参数 | 含义 | 出、入参类型 | 说明 |
account | 账号 | 入参 |
|
password | 密码 | 入参 |
|
处理逻辑 | |||
如果超过阈值,则将用户设置为锁定状态,记录锁定时间,返回错误消息“登录失败超过X次,用户已锁定,请Y分钟后重试”。 |
方法 | private Boolean checkLockedAccount(User user) | ||
参数 | 含义 | 出、入参类型 | 说明 |
user | 用户信息 | 入参 |
|
处理逻辑 | |||
|
方法 | private void lockAccount(User user) | ||
参数 | 含义 | 出、入参类型 | 说明 |
user | 用户信息 | 入参 |
|
处理逻辑 | |||
|
方法 | private Boolean unlockAccount(User user) | ||
参数 | 含义 | 出、入参类型 | 说明 |
user | 用户信息 | 入参 |
|
处理逻辑 | |||
|
图 验证码处理组件
类名 | 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 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。