Java 關於生成WebService客戶端以及服務端存在賬號密碼登入如何通過程式碼模擬登入解決方案
首先,這篇文章主要是用來做一個記錄,方便以後使用,所以不會有太多關於webService以及wsdl的一些原理上的講解,主要是為了解決實際問題,即:如何生成webService客戶端去呼叫服務端,以及當服務端需要進行賬號密碼登入時,我們該如何模擬登入,來繼續呼叫裡面的介面。
主要是因為發現網上關於生成客戶端以及呼叫的文章確實有很多,但是隻要一涉及到服務端有賬號密碼的問題的解決方案就是少之又少,真正找到的有無法使用,所以才寫這篇部落格希望可以幫助同學們節省一些時間。好了,廢話不多說了,直接上操作流程
1.客戶端生成
首先,我們來生成客戶端,因為此篇文章主要是解決服務端有賬號密碼的情況,所以咱們直接以有賬號密碼的服務端url來進行講解和說明,首先一般的各種生成工具對直接輸入賬號密碼生成客戶端支援貌似都並不是很好(至少本人一直沒有成功,也可能是操作問題)。所以,我會使用手動訪問將其xml下載到本地進行本地檔案的匯入。
1.匯出wsdl的xml檔案
1.1 訪問url,輸入賬號密碼
1.2 進入後我們在頁面右鍵另存為,將xml檔案存到我們桌面,並將其後綴改為wsdl.
1.3 生成客戶端
我這裡使用的是idea自帶的外掛,網上也有很多基於dos的生成客戶端的工具,自行選擇即可。
首先,在要生成客戶端的包下點選右鍵,選擇WebService->Generate Java Code From Wsdl
生成後如下圖所示
2.呼叫
正常情況下,如果服務端未設定賬號和密碼,其實我們已經可以進行呼叫,程式碼如下
public class cs {
public static void main(String[] args) {
ISysNotifyTodoWebServiceService is = new ISysNotifyTodoWebServiceService();
ISysNotifyTodoWebService iSysNotifyTodoWebService = is.getISysNotifyTodoWebServicePort();
NotifyTodoSendContext context = new NotifyTodoSendContext();
context.setSubject("測試待辦webservice~~~" );
context.setLink("http://news.sina.com.cn/");
context.setType(2);
context.setKey("sinaNews");
context.setModelId("123456789");
context.setTargets("{\"Id\":\"12fe2de141b7b97b32d1af34204a9f54\"}");
try {
NotifyTodoAppResult notifyTodoAppResult = iSysNotifyTodoWebService.sendTodo(context);
System.out.println(notifyTodoAppResult);
} catch (Exception_Exception e) {
e.printStackTrace();
}
}
}
執行結果如下
報錯401,其實我們在訪問wsdl的url時如果不輸入賬號密碼也會給我們報401,所以證明我們的賬號密碼並沒有被設定,那我們現在需要的就是設定賬號密碼,但問題是,我們到底要在哪裡設定賬號密碼。不賣關子了,核心程式碼如下。
static {
java.net.Authenticator.setDefault(new java.net.Authenticator() {
@Override
protected java.net.PasswordAuthentication getPasswordAuthentication() {
return new java.net.PasswordAuthentication("賬號",
"密碼".toCharArray());
}
});
}
執行結果如下
這次訪問成功,證明我們的賬號密碼唄設定好了,問題是解決了,但是核心問題到底在哪?這個賬號密碼到底是什麼原理設定到了什麼地方才讓我們通過了驗證?
3.HTTP基本認證(Basic Authentication)
其實webService設定了賬號密碼的流程是使用了Basic Authentication,我們所設定的賬號密碼其實會被以key:value經過basic64計算成字串寫到request頭中。不相信?我們來看一下我們訪問的wsdl路徑的requestHeader
我們會看到頭裡有個Authorization的key, value值為我們不知道的一個字串,那我們來試一下自己講這個配置寫入到頭中,看看是否能跳過登入。
3.1 連線測試
我們先隨便找個網上base64線上加密工具將我們的賬號密碼以key:value的形式進行加密,我們發現轉換出來的串和我們剛才看到的串是一樣的,如下圖所示。接下來我們來將串寫入到我們的頭中,看是否生效
我們以訪問剛才的wsdl連結為例,我們先不新增Authorization的串讓其報錯
package com.wsdltwo.cs;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/**
* Created by beyondLi
* Date 2018/1/18
* Desc .
*/
public class ClientCs {
public static void main(String[] args) {
URL url;
InputStream is = null;
StringBuffer sb = new StringBuffer();
URLConnection urlConn;
HttpURLConnection htcon;
try {
url = new URL("你的URL");
urlConn = url.openConnection();
/**
* 註釋掉新增串,報401
*/
//urlConn.setRequestProperty("Authorization", "Basic " + "Ymd5X3pjeXEwMTo4MGQ2MDIwYzc3OTI0NzA2YTU0MGU0NTI2YzIwODk2NA==");
htcon = (HttpURLConnection) urlConn;
is = htcon.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int numCharsRead;
char[] charArray = new char[1024];
while ((numCharsRead = isr.read(charArray)) > 0) {
sb.append(charArray, 0, numCharsRead);
}
System.out.println(url.getAuthority());
System.out.println("sb: "+sb);
} catch (IOException e) {
e.printStackTrace();
}
}
}
效果如圖
接下來我們將上面程式碼註釋的設定開啟,在此執行程式碼,效果如圖,成功連線
好了,核心原因就講解到這裡,解決實際問題的話遵循1和2的步驟進行設定即可,後面的程式碼是為了可以讓各位同學可以更好的看到到底我們1,2中的步驟底層都做了哪些操作。