我正在创建一个 webapp,用户可以在其中为某些网络文档设置警报。该日期与一堆其他数据一起存储在 mysql 数据库中,这些数据在插入时使用 AES_ENCRYPT 进行加密。
插入的过程如下所示:
CREATE DEFINER=`service01`@`%` PROCEDURE `insert_secure_alert`(
IN master_secret VARCHAR(100),
IN path VARCHAR(300),
IN creation DATE,
IN expiration DATE,
IN alert_name VARCHAR(300),
IN alert_comment VARCHAR(300)
)
BEGIN
INSERT INTO `fujitsu_consensus_core`.`alert`
(`id`,
`path`,
`creation`,
`expiration`,
`name`,
`comment`)
VALUES
(0,
AES_ENCRYPT(path, master_secret),
AES_ENCRYPT(creation, master_secret),
AES_ENCRYPT(expiration, master_secret),
AES_ENCRYPT(alert_name, master_secret),
AES_ENCRYPT(alert_comment, master_secret));
END
这工作得很好,但是在使用存储过程检索这些数据时我遇到了一些问题。负责此检索的类如下所示:
package com.fujitsu.database;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import com.fujitsu.consensus.helper.StreamToJson;
public class RetrieveSecureAlert extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -6379032803226212817L;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException{
try {
JSONObject obj = StreamToJson.convertStreamToJson(req.getInputStream());
String path = (String) obj.get("path");
CallableStatement cs = AccessObject.getConnectionObject().prepareCall("{CALL `fujitsu_consensus_core`.`retrieve_secure_alert`(?,?}");
cs.setString(1, path);
cs.setString(2, "FUJITSU");
cs.execute();
ResultSet result = cs.getResultSet();
System.out.println("RESULT!");
while(result.next()){
System.out.println(result.getString("id"));
System.out.println(result.getString("decryptd_path"));
System.out.println(result.getString("decrypted_creation"));
System.out.println(result.getString("decrypted_expiration"));
System.out.println(result.getString("decrypted_name"));
System.out.println(result.getString("decrypted_comment"));
}
} catch (ParseException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
相应的 mysql 存储过程如下所示:
CREATE DEFINER=`service01`@`%` PROCEDURE `retrieve_secure_alert`(IN path_key VARCHAR(300), IN master_secret VARCHAR(100))
BEGIN
DECLARE v_encrypted_path VARBINARY(300);
DECLARE v_encrypted_creation VARBINARY;
DECLARE v_encrypted_expiration VARBINARY;
DECLARE v_encrypted_name VARBINARY(300);
DECLARE v_encrypted_comment VARBINARY(300);
SELECT path INTO v_encrypted_path FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);
SELECT creation INTO v_encrypted_creation FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);
SELECT expiration INTO v_encrypted_expiration FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);
SELECT `name` INTO v_encrypted_name FROM fujitsu_consensus_core WHERE path = path = AES_ENCRYPT(path_key, master_secret);
SELECT `comment` INTO v_encrypted_comment FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);
SELECT id,
AES_DECRYPT(v_encrypted_path, master_secret) AS decryptd_path,
AES_DECRYPT(v_encrypted_creation, master_secret) AS decrypted_creation,
AES_DECRYPT(v_encrypted_expiration, master_secret) AS decrypted_expiration,
AES_DECRYPT(v_encrypted_name, master_secret) AS decrypted_name,
AES_DECRYPT(v_encrypted_comment, master_secret) AS decrypted_comment
FROM fujitsu_consensus_core.alert
WHERE path = AES_ENCRYPT(path_key, master_secret);
END
堆栈跟踪:
java.sql.SQLException: Unable to retrieve metadata for procedure.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
at com.mysql.jdbc.CallableStatement.extractProcedureName(CallableStatement.java:659)
at com.mysql.jdbc.CallableStatement.determineParameterTypes(CallableStatement.java:498)
at com.mysql.jdbc.CallableStatement.<init>(CallableStatement.java:403)
at com.mysql.jdbc.Connection.parseCallableStatement(Connection.java:4161)
at com.mysql.jdbc.Connection.prepareCall(Connection.java:4235)
at com.mysql.jdbc.Connection.prepareCall(Connection.java:4209)
at com.fujitsu.database.RetrieveSecureAlert.doPost(RetrieveSecureAlert.java:29)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
所以最大的问题是,如何使用解密我的记录的 java.sql.callablestatement 从 mysql 中的存储过程中检索记录?