iuap-security组件简介
业务需求
能够提供安全访问时候请求的签名、验证,传输,简单数据加密解密,编码解码等功能,包含对Hmac、RSA等算法的封装,方便业务开发使用。
解决方案
iuap-security组件引入OWASP组织的开源项目ESAPI,利用ESAPI,平台实现了对跨站脚本攻击(XSS),sql脚本注入等安全问题的预防。 ESAPI具有一个安全接口集,其对每一种安全控制有一种参考实现并支持自定义实现。组件在ESAPI的基础上进行扩展。加入了对HTML、CSS、JavaScript、XML、URL等编码与解码,信息的加密解密,信息的摘要签名,防sql注入等功能的API。
iuap-security组件通过可配置的方式提供ESAPI给开发人员使用,方便了业务开发人员使用,iuap-security提供了rest api的签名和验签,在调用端和服务端分别做信息的摘要和验证,确保数据的完整性,防止恶意篡改。
功能说明
- RestAPI签名和验签
- 编码和解码
- 加密和解密
整体设计
依赖环境
组件采用Maven进行编译和打包发布,其对外提供的依赖方式如下:
<dependency>
<groupId>com.yonyou.iuap</groupId>
<artifactId>iuap-security</artifactId>
<version>${iuap.modules.version}</version>
</dependency>
${iuap.modules.version} 为平台在maven私服上发布的组件的version。
使用说明
属性文件配置
application.properties配置示例:
#RSA数字签名算法,目前JDK支持MD2withRSA,MD5withRSA,SHA1withRSA,都是1024bits
UAP.DigitalSignatureAlgorithm=SHA1withRSA
#RSA秘钥长度1024/2048
UAP.DigitalSignatureKeyLength=1024
#随机算法
UAP.RandomAlgorithm=SHA1PRNG
#HMAC摘要算法,目前jdk支持:HmacSHA1 (160 bits), HmacSHA256 (256 bits), HmacSHA384 (384 bits),HmacSHA512 (512 bits).
UAP.KDF.PRF=HmacSHA1
#签名或者摘要算法目前支持HMAC、RSA.
UAP.AUTH.ALG=HMAC
#客户端身份文件路径
bpm.client.credential.path=/etc/authfile_bpm.txt
#如果客户端需要用多个服务提供的证书,可以通过appid来区分不同的证书目录
#appid.client.credential.path=/etc/authfile_appid.txt
示例工程中的antisamy-esapi.xml、ESAPI.properties、validation.properties在jar包中已经包含,如果没有需要覆盖的属性,则不需要添加。ESAPI.properties中如果需要覆盖Encryptor.MasterKey和Encryptor.MasterSalt的值,请参考示例工程中的setMasterKey.bat,生成新值,并覆盖到classpath中的ESAPI.properties中。
API接口
RestAPI签名
在请求端,根据URL参数(含ts值)、请求端IP地址、表单参数以及Content-Length的大小进行生成签名sign。
SignProp prop = SignPropGenerator.genSignProp(url);
signProp.setIp(ip);
//post请求时需要
signProp.setPostParamsStr(PostParamsHelper.genParamsStrByMap(parameter));
signProp.setContentLength(ContentLength);
String sign = ClientSignFactory.getSigner(cert).sign(prop);
注意:如果配置多份客户端证书,需要在getSinger的时候指定前缀,示例如下:
ClientSignFactory.getSigner("bpm")
SignProp中包含的参数说明
参数名 | 必选 | 类型 | 说明 |
---|---|---|---|
ts | true | 字符串 | 请求发出的时间戳,在请求的url中 |
ip | false | 请求端IP地址 | 请求端IP地址 |
postParamsStr | false | 字符串 | POST表单参数Map生成的字符串,可以调用PostParamsHelper中的方法生成 |
contentLength | false | 字符串 | HttpServletRequest中取得的Content-Length的值 |
返回值
sign 生成的验证签名,类型为字符串。
RestAPI验签
描述
在服务端,首先比较当前时间ts’与ts的大小,如果其差值不大于DEFAULT_EXPIRED,则从HTTP请求中获得时间戳ts、URL参数、请求的来源IP地址、表单参数以及ContentLength的大小生成sign’。此时如果sign与sign’相同,则签名验证通过
SignProp prop = SignPropGenerator.genSignProp(url);
//服务端需要获取客户端的真实ip
signProp.setIp(ip);
//post请求时需要
signProp.setPostParamsStr(PostParamsHelper.genParamsStrByMap(request));
//在服务端获取请求的contentLength
signProp.setContentLength(contentLength);
DemoServerVirifyFactory factory = new DemoServerVirifyFactory();
Boolean result = factory.getVerifier(appid).verify(sign, prop);
DemoServerVirifyFactory为开发者实现的类,需要实现获取证书的方法。
参数说明
参数名 | 类型 | 说明 |
---|---|---|
appid | 字符串 | 服务端存储的证书中对应的客户端的唯一标识 |
sign | 字符串 | 请求中传入的sign,用来与服务端生成的sign进行对比 |
prop | SignProp | 需要验证签名的参数集合对象 |
返回值
验证是否成功,类型为boolean。
编码
描述
数据编码分为多种形式,如html编码、javascript编码、css编码、sql编码等,它们主要是用来解决各类注入问题:xss注入、sql注入。除此之外,还有Base64编码,常用来将非ASCII字符的数据转换成ASCII字符
请求方法
html编码
String safe =IUAPESAPI.encoder().htmlEncode( input);
属性编码
String safe =IUAPESAPI.encoder().htmlAttributeEncode (input);
js编码
String safe =IUAPESAPI.encoder().javaScriptEncode ( input);
url编码
String safe =IUAPESAPI.encoder().urlEncode (input);
css编码
String safe =IUAPESAPI.encoder().cssEncode ( input);
sql注入示例
String queryCondition = IUAPESAPI.encoder().sqlPreparedString( input,paras, DatabaseCodec.ORACLE);
base64
String base64Text = IUAPESAPI.encoder().encodeForBase64(input);
请求参数说明
参数名 | 类型 | 说明 |
---|---|---|
input | 字符串 | 要编码的内容 |
返回值
编码后的字符串。
对称加密算法
功能描述
对称加密算法可以用作存储加密,即将数据持久化前对数据进行加密。
加密
请求方法
String safe = IUAPESAPI.encryptor().encrypt(input);
参数说明
参数名 | 类型 | 说明 |
---|---|---|
input | 字符串 | 要加密的内容 |
返回值
加密后的字符串。
解密
请求方法
String safe = IUAPESAPI.encryptor(). decrypt(input);
参数说明
参数名 | 类型 | 说明 |
---|---|---|
input | 字符串 | 要解密的内容 |
返回值
解密后的字符串。
非对称加密算法
描述
非对称加密算法可以用作传输加密,即数据从请求端发送到服务端时,对敏感数据用公钥进行加密,在服务端用私钥进行解密,这里我们提供了RSAUtils工具类进行RSA加密。
加密
请求方法
//首次生成公钥的示例
KeyPair gk = RSAUtils.generateKeyPair();
RSAPublicKey publicKey = RSAUtils.getDefaultPublicKey();
//调用方法进行加密
byte[] encryptBytes = RSAUtils.encrypt(publicKey, input.getBytes());
参数说明
参数名 | 类型 | 说明 |
---|---|---|
publicKey | RSAPublicKey | 公钥 |
input | byte[] | 要解密的内容的字节数组 |
返回值
加密后的二进制数组。
解密
请求方法
RSAPrivateKey privateKey = RSAUtils.getDefaultPrivateKey();
byte[] data = RSAUtils.decrypt(privateKey, encryptBytes);
参数说明
参数名 | 类型 | 说明 |
---|---|---|
privateKey | RSAPrivateKey | 私钥 |
encryptBytes | byte[] | 要解密的内容的字节数组 |
返回值
解密后的内容,类型为字节数组。
更加详细的配置和示例请参考示例工程(DevTool/examples/example_iuap_security)