1. 问题描述
用户在登录数据决策系统时需要进行 用户身份验证 ,系统会对输入的用户名和密码进行验证,以确保系统安全。
登录验证信息(用户名和登录密码)存储在数据库(FineReport 内置数据库 FineDB 或者其他外接数据库)中,验证时用户输入的密码与数据库中密码相同则验证通过。
若数据库被破解,则登录验证信息暴露,对系统安全造成威胁。怎样避免此类情况,保证系统安全呢?
2. 解决方案
用户可以对数据库中的登录信息进行加密。保证即使数据库被破解,也无法得到用户的真正登录信息。
同时,FineReport 在 同步用户 中提供「自定义密码加密」方式,可以对用户在登录页输入的登录信息进行加密。当加密后的登录信息与 FineDB 库中的登录信息一致时,验证通过。如下图所示:
加密简介:自定义密码加密,即自定义一个密码加密类。
加密方式在类中描述,并保存在%FR_Home%\webapps\webroot\WEB-INF\classes文件夹中。
数据决策系统会在用户自定义加密算法的基础上再进行 SHA256 二次加密,以保证密码安全。
适用场景:同步的服务器数据集中的密码为自定义加密后的密文时,必须使用自定义加密。
加密接口:通过接口编写自定义密码加密类,对用户输入的“密码”或“用户名和密码”经过自定义加密规则进行加密。支持的接口如下:
1)只需要对密码进行加密得到密文:String encode(String originText);//入参是明文密码,对密码进行加密得到密文
2)对用户名和密码进行加密得到密文:String encode(String originUserName, String originPassword);//入参是用户名和明文密码,返回结果是密文字符
注1:其中 String encode(String originUserName, String originPassword);加密方式为 2019-01-18 新增的接口,包含接口1的功能,推荐使用此接口。
注2:自定义加密算法,必须继承 AbstractPasswordValidator 类。
3. 实现思路
3.1 加密验证逻辑
如果用户在登录页面输入明文密码后,能够成功登录数据决策系统。那么在这个过程中会进行三次加密和一次登录验证。
同步用户后发生:
1)第一次加密:同步用户后,系统会对服务器数据集中的密文进行一次 SHA256 加密,得到的密文写入 FineDB 库。
用户登录时发生:
2)第二次加密:自定义密码加密,加密对象为用户输入的明文密码。
3)第三次加密:系统统一进行的 SHA256 加密,加密对象为第二次加密后的密文。
4)登录验证:对比第三次加密后得到的密文与 FineDB 库中的密文,一致则验证通过。
如下图所示:
3.2 实现步骤
1)自定义一个密码加密类,用于加密用户在登录页面输入的明文密码 A。
准备编译环境
编写 Java 文件
编译 class 文件
2)创建服务器数据集,存储用户的登录信息,包括用户名、登录密码等,其中登录密码为自定义加密后的密文 B。
注:同步用户后,系统会对服务器数据集中该密文进行一次 SHA256 加密,得到的密文写入 FineDB 库。
3)同步用户信息至数据决策平台,用于系统登录验证。
用户来源为步骤 2 中准备的服务器数据集。
密码选择服务器数据集中的密码,为自定义加密后的密文。
设置加密方式为自定义加密,使用步骤 1 中准备的密码加密类。
4. 自定义密码加密示例
本文示例:编写 BASE64 密码加密类,对用户输入的“密码”经过自定义加密规则进行加密,然后进行登录验证,成功登录数据决策系统。
注:本文仅对 Base64 加密方式进行简单示例,对于其他常见的加密方式,本文在第五节提供自定义类文件,用户可以根据自己的需求下载使用。
4.1 准备编译环境
编译程序前,需先创建一个 Java 工程环境,并且需要一个 Java 编辑器,如 Eclipse 或 idea 。
在编辑器下打开工程,选择「Properties>Java Build Path>Libraries」,导入 FineReport 工程 JAR 包,详细操作可参考:编译Java程序
4.2 编写Java文件
在编译器中定义一个类,命名为 Base64PasswordValidator.java,扩展于 AbstractPasswordValidator。Java 代码如下:
package com.fr.decision.privilege.encrpt;;
import com.fr.base.Base64;
import com.fr.base.ServerConfig;
import com.fr.decision.privilege.encrpt.AbstractPasswordValidator;
import com.fr.log.FineLoggerFactory;
import java.io.UnsupportedEncodingException;
public class Base64PasswordValidator extends AbstractPasswordValidator {
public Base64PasswordValidator() {
}
public String encode(String originText) {
try {
return Base64.encode(originText.getBytes(ServerConfig.getInstance().getServerCharset()));
} catch (UnsupportedEncodingException var3) {
FineLoggerFactory.getLogger().debug(var3.getMessage());
return "";
}
}
}
4.3 编译class文件
点击下载并解压获得 class 文件:Base64PasswordValidator.zip
1)生成 class 文件
编译 Base64PasswordValidator.java,生成 Base64PasswordValidator.class 文件。
2)导入 class 文件
将编译后的 Base64PasswordValidator.class 文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege/encrpt文件夹下。
4.4 创建服务器数据集
用户需要对数据库中的登录信息进行 BASE64 加密。然后由系统再次进行 SHA256 加密,最终写入 FineDB 库,用于登录校验。保证即使数据库被破解,也无法得到用户的真正登录信息。
4.4.1 数据准备
准备一张用户信息表,其中 password 数据列中的密码为 BASE64 加密后的密文。表结构如下图所示:
示例:若用户 a 在登录页面实际输入的明文密码为:123456,则 password 列中存放的密码为 BASE64 加密后的密文:MTIzNDU2
点击下载用户信息表:同步用户.xlsx
4.4.2 新增服务器数据集
请自行使用第三方数据库管理工具,将上表导入数据库,并建立系统与该数据库的 数据连接 。下文将以 FRDemo 数据库为例。
1)管理员登录数据决策系统,点击「管理系统>数据连接>服务器数据集」,创建「SQL数据集」。如下图所示:
2)设置数据集名称为「同步用户」,数据连接选择「FRDemo」,SQL 语句为:
select * from 导入用户
4.5 设置加密方式
注:若用户选择其他自定义密码加密方式,可在本节 4.5.2 中更改自定义加密类。本文在第五节提供了常用的自定义加密类文件,用户可按需选用。
在同步用户中可以选择自定义密码加密方式来提升系统的安全性。
4.5.1 同步用户
1)管理员登录数据决策系统,点击「管理系统>用户管理>所有用户」,点击「同步用户」。
跳出提示框「是否保留现有非同步数据,包括导入/添加的用户、部门职务、角色」,如下图所示:
注1:本章是针对「之前从未进行过同步用户」、「同步用户未开启状态下执行首次同步操作」的数据更新规则。
若之前同步过用户,在同步用户开启状态下执行非首次同步操作将不会出现此节提示弹窗,也不会按照此节中更新规则进行同步。
注2:同步的用户与「手动添加/导入的用户」可并存。
不同选择对应的更新逻辑如下:
选择 | 定义 |
---|---|
保留 | 如果现有用户不在同步的服务器数据集中,该用户信息和权限将被保留,不修改 如果现有用户在服务器数据集中(用户名相同):
|
清空 | 平台现有「手动添加/导入的用户」的用户名、姓名、密码、手机、邮箱、部门、职务、角色、权限均被删除,重新同步用户 |
注:根据选择的更新逻辑,首次同步后有部分用户信息被更新。
之后能被自动更新的只有已变为同步类型的用户。
之后的同步,数据集不能再覆盖更新内置数据,否则将冲突报错。
4.5.2 加密配置
1)用户来源选择为:4.4.2 中准备的服务器数据集「同步用户」
2)密码选择为:password
3)加密方式选择为:自定义密码加密,使用 4.3 节中准备的 Base64PasswordValidator.class 自定义加密类
如下图所示:
注:如需使用自定义加密方法,在 同步用户 的时候,不能勾选「用户可编辑」选项,否则会导致用户无法登录。
点击「确定」,同步用户成功。如下图所示:
4.6 效果预览
用户 a 登录数据决策系统:
服务器数据集中用户 a 的密文:MTIzNDU2 ,其解密后的明文:123456
在登录页面输入明文密码:123456,点击「登录」,成功登录数据决策系统。如下图所示:
5. 常用的自定义密码加密方式
本文提供了常用的自定义密码加密方式文件,用户可根据需求使用。点击下载文件后放到指定文件夹下,并更改 4.5.2 节中的自定义类,其余步骤参照第四节示例即可。
5.1 BASE64加密用户名和密码
FineReport 支持使用 BASE64 加密方式对用户输入的用户名和密码一起进行加密。
现提供编译后的 BASE64 加密类,点击下载文件:Base64UserPasswordValidator.zip
1)点击下载并解压后,将文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege文件夹下。
2)配置服务器数据集中 password 列为“用户名+密码”的 BASE64 加密密文。
示例:用户 a 的密码是 123456,则服务器数据集中,password 列应该是 a123456 的 BASE64 加密密文“YTEyMzQ1Ng==”
5.2 SHA256加密密码
FineReport 支持使用 SHA256 加密方式对用户输入的密码进行加密。
现提供编译后的 SHA256 加密类,点击下载文件:SHA256PasswordValidator.zip
点击下载并解压后,将文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege/encrpt文件夹下。
5.3 SHA256加密用户名和密码
FineReport 支持使用 SHA256 加密方式对用户输入的用户名和密码一起进行加密。
现提供编译后的 SHA256 加密类,点击下载文件:CustomSHA256PasswordValidator.zip
1)点击下载并解压后,将文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege/encrpt文件夹下。
2)配置服务器数据集中 password 列为“用户名+密码”的 SHA256 加密密文。
示例:用户 a 的密码是 123456,则服务器数据集中,password 列应该是 a123456 的 SHA256 加密密文“20f645c703944a0027acf6fad92ec465247842450605c5406b50676ff0dcd5ea”
5.4 MD5(32位小写)加密密码
FineReport 支持使用 MD5(32位小写)加密方式对用户输入的密码进行加密。
现提供编译后的 MD5(32位小写)加密类,点击下载文件:MD5CasePasswordValidator.zip
点击下载并解压后,将文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege文件夹下。
5.5 MD5(32位小写)加密用户名和密码
FineReport 支持使用 MD5(32位小写)加密方式对用户输入的用户名和密码一起进行加密。
现提供编译后的 MD5(32位小写)加密类,点击下载文件:MD5CaseUserPasswordValidator.zip
1)点击下载并解压后,将文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege文件夹下。
2)配置服务器数据集中 password 列为“用户名+密码”的 MD5 加密密文。
示例:用户 a 的密码是 123456,则服务器数据集中,password 列应该是 a123456 的 MD5(32位小写)加密密文“dc483e80a7a0bd9ef71d8cf973673924”
5.6 MD5(32位大写)加密密码
FineReport 支持使用 MD5(32位大写)加密方式对用户输入的密码进行加密。
现提供编译后的 MD5(32位大写) 加密类,点击下载文件:MD5UpperCasePasswordValidator.zip
点击下载并解压后,将文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege文件夹下。
5.7 MD5(32位大写)加密用户名和密码
FineReport 支持使用 MD5(32位大写)加密方式对用户输入的用户名和密码一起进行加密。
现提供编译后的 MD5(32位大写)加密类,点击下载文件:MD5UpperCaseUserPasswordValidator.zip
1)点击下载并解压后,将文件保存到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/decision/privilege文件夹下。
2)配置服务器数据集中 password 列为“用户名+密码”的 MD5(32位大写)加密密文。
示例:用户 a 的密码是 123456,则服务器数据集中,password 列应该是 a123456 的 MD5(32位大写)加密密文“DC483E80A7A0BD9EF71D8CF973673924”
6. 注意事项
6.1 9.0 版本升级后无法登录数据决策系统
原因分析:
9.0 版本 FineReport 内置的 MD5 加密方式不区分密文大小写。
10.0 版本 FineReport适配的 MD5 加密方式区分大小写。
9.0 同步选择内置 MD5 加密,升级后会内置一个小写 MD5 的 class,如果是大写密文,升级后就不能登录。
解决方案:
本文在第五节提供了 MD5 的自定义加密类文件,用户可下载 MD5 的大写 class 文件,并替换到相应路径下。
6.2 NoClassDefFoundError
问题描述:
设置自定义加密方式后,同步用户失败,报错:NoClassDefFoundError: com/fr/decision/privilege/Base64PasswordValidator (wrong name: com/fr/decision/privilege/encrpt/Base64PasswordValidator)
原因分析:
自定义加密类 class 文件保存路径错误。
解决方案:
报错信息中,wrongname:后的路径为正确路径,将 class 文件移动至正确路径下,重新设置加密方式即可。