我正在研究 Web 服务安全性,尝试在服务器和客户端之间加密和签署 SOAP 消息。我使用了 BouncyCastle、WSS4j 和 SOAP 处理程序。
为了测试我的工作,我在服务器端和客户端都使用了相同的密钥库文件。我按照网上的一些教程进行操作,它起作用了:一侧发送的消息经过加密和签名,然后在另一侧成功解密.
但是现在我为服务器和客户端生成了不同的证书,并将客户端的证书导入到服务器的 jks 文件中,反之亦然,我似乎无法弄清楚如何完成任务。它仍在加密和签名,就好像它只有一个没有导入证书的 jks 文件一样。下面是代码:
Crypt_handler.java
public class Crypt_handler implements SOAPHandler<SOAPMessageContext> , CallbackHandler{
public Properties prop;
public InputStream input= null;
public Crypt_handler () {
try {
prop=new Properties();
input = new FileInputStream("config.properties");
if(input==null){
System.out.println("Sorry, unable to find " );
return;}
prop.load(input);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean handleMessage(SOAPMessageContext messageContext) {
try {
// got the message from the context
SOAPMessage msg = messageContext.getMessage();
// is outgoing?
Boolean isOutGoing = (Boolean) messageContext
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (isOutGoing) {
// if it is outgoing code and sign
crypt.EncryptUtil.EncryptSOAPEnvelope(msg, prop);
crypt.EncryptUtil.SignSOAPEnvelope(msg, prop);
} else {
// if it is incooming decode and check signature.
crypt.EncryptUtil.CheckSignatureAndDecode(msg, this , prop);
}
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex.getMessage());
}
return true;
}
public boolean handleFault(SOAPMessageContext context) {
System.out.println("Server : handleFault()......");
return true;
}
public void close(MessageContext context) {
System.out.println("Server : close()......");
}
public Set<QName> getHeaders() {
Set<QName> HEADERS = new HashSet<QName>();
HEADERS.add(new QName(WSConstants.WSSE_NS, "Security"));
HEADERS.add(new QName(WSConstants.WSSE11_NS, "Security"));
HEADERS.add(new QName(WSConstants.ENC_NS, "EncryptedData"));
return HEADERS;
}
private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
try {
SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
SOAPFault soapFault = soapBody.addFault();
soapFault.setFaultString(reason);
throw new SOAPFaultException(soapFault);
}
catch(SOAPException e) { }
}
@SuppressWarnings("deprecation")
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
String password;
for (Callback cb : callbacks) {
if (cb instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) cb;
try {
password = /*prop.getProperty("password")*/"password";
} catch (Exception e) {
throw new UnsupportedCallbackException(pc, "failure recovering the key in the properties");
}
if (pc.getIdentifer() != null) {
pc.setPassword(password);
}
}
}
}
}
EncryptUtil.java:
public class EncryptUtil{
@SuppressWarnings( { "unchecked", "deprecation" })
public
static void CheckSignatureAndDecode(SOAPMessage msg, CallbackHandler cb,Properties prop) throws WSSecurityException, TransformerConfigurationException, TransformerException, SOAPException, IOException, Exception {
WSSecurityEngine secEngine = new WSSecurityEngine();
WSSignEnvelope signer = new WSSignEnvelope();
String alias = prop.getProperty("alias");// login of jks file
String password = prop.getProperty("password");// password of jks file
signer.setUserInfo("client", password);
Crypto crypto = CryptoFactory.getInstance(prop);
Document doc = toDocument(msg);
//after we set the encrypt stuff the processsecurity does all the work
Vector v = secEngine.processSecurityHeader(doc, null, cb, crypto);
if (v == null) {
throw new Exception("Access not granted.");
}
//put the decoded message into the object
updateSOAPMessage(doc, msg);
}
/**
* Updates the message with the unencrypt form
*/
private static SOAPMessage updateSOAPMessage(Document doc, SOAPMessage message) throws SOAPException {
DOMSource domSource = new DOMSource(doc);
message.getSOAPPart().setContent(domSource);
return message;
}
/**
* Changes the SOAPMessage to a dom.Document.
*/
public static org.w3c.dom.Document toDocument(SOAPMessage soapMsg) throws SOAPException, TransformerException {
Source src = soapMsg.getSOAPPart().getContent();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMResult result = new DOMResult();
transformer.transform(src, result);
return (Document) result.getNode();
}
/**
* Signs a SOAPMessage
*
* @param mensaje
* @throws Exception
*/
@SuppressWarnings("deprecation")
public
static void SignSOAPEnvelope(SOAPMessage mensaje, Properties prop) throws Exception {
// WSSignEnvelope signs a SOAP envelope according to the
// WS Specification (X509 profile) and adds the signature data
// to the envelope.
WSSignEnvelope signer = new WSSignEnvelope();
String alias = prop.getProperty("alias");// "autentiaserver";
String password = prop.getProperty("password");// "changeit";
signer.setUserInfo(alias, password);
Crypto crypto = CryptoFactory.getInstance(prop);
Document doc = toDocument(mensaje);
signer.setMustUnderstand(false);
Document signedDoc = signer.build( doc, crypto);
DOMSource domSource = new DOMSource( signedDoc);
mensaje.getSOAPPart().setContent(domSource);
}
/**
* Codes a SOAPMessage.
*/
@SuppressWarnings("deprecation")
public
static void EncryptSOAPEnvelope(SOAPMessage mensaje,Properties prop) throws Exception {
// WSSignEnvelope signs a SOAP envelope according to the
// WS Specification (X509 profile) and adds the signature data
// to the envelope.
WSEncryptBody encriptador = new WSEncryptBody();
String alias = prop.getProperty("alias");
String password = prop.getProperty("password");
encriptador.setUserInfo(alias, password);
Crypto crypto = CryptoFactory.getInstance(prop);
Document doc = toDocument(mensaje);
encriptador.setMustUnderstand(false);
Document signedDoc = encriptador.build( doc, crypto);
DOMSource domSource = new DOMSource( signedDoc);
mensaje.getSOAPPart().setContent(domSource);
}
}
这是我的 config.properties 文件:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=password
org.apache.ws.security.crypto.merlin.keystore.alias=first
org.apache.ws.security.crypto.merlin.file=/home/user/workspace/crypt_server/keystore.jks
alias=first
password=password
任何帮助,将不胜感激。提前致谢。