我需要编写Java SOAP客户端代码来根据客户的请求使用Web服务。当我调用Java客户端代码时,我收到401未经授权的响应代码。但是,当我从邮递员那里打电话时,一切都很好。这是Java客户端代码。
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.client.AuthCache;
import org.apache.http.impl.client.BasicAuthCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.*;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
Logger log = LoggerFactory.getLogger(DemoApplication.class);
static {
//disableSslVerification();
}
public static void disableSslVerification() {
try
{
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
private final String REALM = "Restricted";
private final String SEPARATOR = ", ";
private final String QUOTE = "\"";
private final String NONCE = Long.toString(new Random().nextLong(), 36);
private String setAuthorizationHeader(String method, String username, String password,String nonce) throws AuthenticationException {
DigestScheme digestScheme = new DigestScheme();
Map<String,String> params = new HashMap<>();
String digest4 = DigestUtils.sha1Hex(username + ":" + REALM + ":" + password +new Date().getTime());
String digest2 = DigestUtils.md5Hex(method + ":" + "/");
params.put("uri","/soap/sp");
params.put("realm","Restricted");
params.put("nonce",nonce);
params.put("nc","01");
params.put("cnonce","0a458m12");
params.put("qop","auth");
params.put("methodname","POST");
params.put("algorithm","MD5");
String md5Hex = DigestScheme.createDigest("arbor","arbortt",params);
String header = DigestScheme.createDigestHeader("arbor",params,md5Hex);
String value = "Digest " + header;
return value;
}
public String calculateNonce() {
Date d = new Date();
SimpleDateFormat f = new SimpleDateFormat("yyyy:MM:dd:hh:mm:ss");
String fmtDate = f.format(d);
Random rand = new Random(100000);
Integer randomInt = rand.nextInt();
return DigestUtils.sha1Hex(fmtDate + randomInt.toString());
}
@Override
public void run(String... args) throws Exception {
System.setProperty("javax.net.ssl.trustStore","C:\\Users\\devuser\\Desktop\\keystorefile");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
disableSslVerification();
RestTemplate restTemplate = new RestTemplate();
String request = "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:com.example.demo.PeakflowSP\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <urn:getDosAlertSummaries soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
" <filter xsi:type=\"xsd:string\"></filter>\n" +
" <count xsi:type=\"xsd:unsignedInt\"></count>\n" +
" </urn:getDosAlertSummaries>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
headers.setContentType(MediaType.APPLICATION_XML);
String nonce = calculateNonce();
headers.add("ETag",nonce);
headers.add("Authorization",setAuthorizationHeader("getDosAlertSummaries","arbor","arbortt",nonce));
HttpEntity<String> entity = new HttpEntity<>(request, headers);
ResponseEntity<String> response = restTemplate.postForEntity("https://10.34.34.71/soap/sp", entity, String.class);
String str = response.getBody();
str = str.replace("xsi:type=\"ns1:DosAlertSummaryArray\"","");
str = str.replace("xsi:type=\"xsd:unsignedInt\"","");
str = str.replace("xsi:type=\"xsd:string\"","");
str = str.replace("xsi:type=\"xsd:boolean\"","");
str = str.replace("xsi:type=\"ns1:DosAlertSummary\"","");
str = str.replace("xsi:type=\"ns1:AlertDirection\"","");
str = str.replace("xsi:type=\"xsd:float\"","");
str = str.replace("xsi:type=\"xsd:dateTime\"","");
str = str.replace("xsi:type=\"ns1:AlertResource\"","");
str = str.replace("xsi:type=\"ns1:AlertManagedObject\"","");
str = str.replace("xsi:type=\"ns1:AlertImportance\"","");
str = str.replace("xsi:type=\"ns1:Annotation\"","");
str = str.replace("xsi:type=\"ns1:unitType\"","");
log.info(response.toString());
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(str));
xsr.nextTag();
xsr.nextTag();
xsr.nextTag();
xsr.nextTag();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter stringWriter = new StringWriter();
transformer.transform(new StAXSource(xsr), new StreamResult(stringWriter));
StringReader sr = new StringReader(stringWriter.toString());
JAXBContext jaxbContext = JAXBContext.newInstance(DosAlertSummaries.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
DosAlertSummaries loginResult = (DosAlertSummaries) unmarshaller.unmarshal(sr);
}
}
这是来自程序的请求日志:
Digest username="arbor", realm="Restricted",
nonce="d90b71aa44b311113dd392e64e6d9347444d3b40",
uri="/soap/sp", qop="auth", algorithm="MD5", nc=01, cnonce="0a458m12",
response="297349367d0faa283a6649a004e104d1"
邮递员请求日志:
Digest username="arbor", realm="Restricted",
nonce="Nf7oZOFzBQA=04e0c7c96bad6b7d2eabe2ec03831f55c13cde0d",
uri="/soap/sp", algorithm="MD5", qop=auth, nc=01, cnonce="0a458m12",
response="480da02481f50f76a7fbc82a63869e2e"
向邮递员请求xml:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getDosAlertSummaries xmlns:ns1="urn:com.example.demo.PeakflowSP"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<filter xsi:type="xsd:string" />
<count xsi:type="xsd:unsignedInt">100</count>
</ns1:getDosAlertSummaries>
</soapenv:Body>
</soapenv:Envelope>
当我采用邮递员创建的现时值而不是用代码计算时,我得到200。有人可以告诉我我做错了什么吗?问题可能是现时价值。如果是,我如何正确计算现时值?
谢谢