用于 Building Block 开发人员的安全 API
Blackboard 已与 Open Web Application Project (OWASP) 的企业安全 API (ESAPI) 中的最佳实践开源安全库集成。默认情况下,此安全库通过名为“ESAPI 安全模块”的构建块安装在 Blackboard 上,并且是系统作所必需的。Blackboard 强烈建议所有 Building Block 开发人员利用这个基于 OWASP ESAPI for Java 和 ESAPI for JavaScript 的新安全 API。这些安全 API 更改不仅包括最佳实践实现,还通过一致的命名法提高了方法的易用性。
注意
在以后的版本中,ESAPI 安全模块构建块 API 是 Blackboard 核心代码的一部分,默认情况下可用。
作为安全编码实践的一部分,可能受用户影响的输入(无论是否可信)都应在处理(输入验证)和显示(输出验证或转义)之前在服务器端进行验证。这有助于确保系统弹性并防止跨站点脚本等安全问题。
输入验证
从请求接收输入时,请始终验证并始终在服务器端验证。Blackboard 已实现几个需要验证的常用用例。下面提供了一些示例。
blackboard.platform.security.ValidationUtility.isValidDirectoryPath( 字符串 )
blackboard.platform.security.ValidationUtility.isValidGuid( 字符串 )
blackboard.platform.security.ValidationUtility.isValidEnumeratedType( 枚举, 字符串 )
输出验证/编码/转义
显示任何输入时,请始终确保它在将嵌入的正确上下文中显示:
Java 方法
blackboard.platform.security.EscapeUtility.escapeForHTML ( 字符串 )
blackboard.platform.security.EscapeUtility.escapeForHTMLAttribute ( 字符串 )
blackboard.platform.security.EscapeUtility.escapeForJavascript ( 字符串 )
blackboard.platform.security.EscapeUtility.escapeForUrl ( 字符串 )
blackboard.platform.security.EscapeUtility.escapeForCSS ( 字符串 )
blackboard.platform.security.EscapeUtility.escapeForXML ( 字符串 )
blackboard.platform.security.EscapeUtility.escapeForXMLAttribute ( 字符串 )
JSP 方法
${bbNG:EscapeForHTML( String )}
${bbNG:EscapeForJavascript( String )}
${bbNG:EscapeForURL( String )}
${bbNG:EscapeForCSS( String )}
${bbNG:EscapeForXML( String )}
${bbNG:EscapeForXMLAttribute( String )}
JavaScript 方法
所有 ESAPI for JavaScript 方法都可供使用。更常用的方法列表:
$ESAPI.encoder().canonicalize( String )
$ESAPI.encoder().encodeForHTML( String )
$ESAPI.encoder().encodeForHTMLAttribute( String )
$ESAPI.encoder().encodeForCSS( String )
$ESAPI.encoder().encodeForJavaScript( String )
$ESAPI.encoder().encodeForURL( String )
破译加密文本
破译加密上下文
要在上下文传递期间加密数据,Blackboard 和外部 URL 必须能够访问相同的上下文加密密钥。必须从管理员面板上提供的管理上下文加密密钥功能创建密钥。创建密钥后,必须将其下载并分发到接受上下文的外部服务器。
代码示例
下载上下文加密密钥后,必须将其提供给将通过上下文传递接收加密数据的 URL。下面的代码示例演示了如何在传递外部 URL 时以编程方式破译外部 URL 上的加密上下文数据。
目标 URL 指示的对象(在本例中为 index.jsp)可以按如下方式解密上下文(导入 blackboard.client.decryption.*):
String context = request.getParameter("context");//if isEncryptionEnabled = false, base 64 encoding will be used instead //of encryptionboolean isEncryptionEnabled = true;ContextDecryptor bfd = ContextDecryptorFactory.getContextDecryptor(isEncryptionEnabled ); // retrieve the Blackboard encryption key as a File or InputStream File key = new File( strKeyLocation ); // or InputStream key = // implementation detail...// to simply decrypt the context string String decryptedContext = bfd.decrypt( context, key );// or, to get a HashMap of all key-value pairsHashMap map = bfd.parseEncryptedContext( context, key );// then search the HashMap for an expected value, and continue.if (map.containsKey( "user" ){ // execute...}
解析多个键
当外部 URL 和 Blackboard 之间存在一对一关系时,上面的代码示例非常有用。对于外部 URL 支持多个 Blackboard 实例的构建块的实例,实例的主机名可用于处理多个键。
在下面的示例中,密钥是通过与 Blackboard 实例或虚拟安装的主机名相关联来找到的。在这种情况下,主机名是 physics.your机构.com。由于客户端解密代码能够将解密密钥传递给 ContextDecryptor 对象,因此客户端服务器必须能够将主机名映射到其适当的密钥(通常作为文件访问,但也可以是 动态)。
Building Block 服务器开发人员可以编写一个简单的包装器,用于:
从请求中提取主机名。
在 hostname-encryptionKey 映射中查找加密密钥文件。
将加密密钥传递给
decrypt()方法。
由客户端服务器实用程序对象实现的伪代码包装器:
/**
* 实用程序伪代码
*/
decryptByHostname( HttpServletRequest 请求)
{
从请求中获取上下文参数
String context = request.getParameter("context");
确定上下文是否已加密
String strEncryptInd = request.getParameter("encrypt");
if ( (strEncryptInd != null) && (strEncryptInd.equalsIgnoreCase("y")) )
{
isEncrypted = true;
}
如果是Encrypted,则查找密钥
key = null;
if (是加密)
{
从 HttpUtils.getRequestURL().getHost() 获取主机名;
get 键映射,可能存储为格式为
// physics.yourinstitution.com= /key/file/location/physics_yourinstitution_com/key.sec
从地图中获取加密密钥作为 File 或 动态,
取决于客户端实现详细信息(如果
// isEncrypted= false, and Base64Encoding is used instead)
}
ContextDecryptor decryptor =
ContextDecryptorFactory.getContextDecryptor(isEncrypted);
然后返回上下文中传递的值作为
键值对的 HashMap
HashMap values = decryptor.parseEncryptedContext(context, key);
或字符串
String values = decryptor.decrypt (context, key);
返回值;
}