📜 ⬆️ ⬇️

Add Basic Auth to a SOAP request using ksoap2-android

It so happened that as part of my work I contacted a project to develop an application for communication Android and 1C. A quick search on the Internet gave quite clear instructions and pieces of code that very quickly formed into a ready-made program, but she did not want to run. Here I will tell the main subtleties and ways to solve them.

The original sources of the code are listed here and here . It is only necessary to connect the third-party ksoap2-android library so that the classes SoapObject and HttpTransportSE become available. The old proven way to download jar from the official repository and put it in app / libs for some reason did not succeed, and I began to look at how to connect the library using modern Gradle. Almost all the resources have been written that a simple addition

dependencies { compile 'com.google.code.ksoap2-android:ksoap2-android:3.6.1' } 

should "pull" the necessary resources. But this did not happen, because the resource itself is not in standard repositories. So, you need to specify where to download it. This is done by adding the following lines to the project's Gradle file:

 buildTypes { repositories { maven { url 'https://oss.sonatype.org/content/repositories/ksoap2-android-releases' } } } 

After these simple steps, just sync the project, and Gradle will download everything you need.
Here is the code that starts working after the above procedures:
')
 public class DataLoader extends AsyncTask<Void, Void, String> { private static final String NAMESPACE = "namespace"; private static final String URL = "http://host/wsdlAcceptor?wsdl"; private static final String SOAP_ACTION = "http://host/wsdlAcceptor"; private static final String METHOD_NAME = "testOperation"; @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(Void... params) { try { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10); request.addProperty("IsFirstRequest", true); envelope.setOutputSoapObject(request); HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); androidHttpTransport.debug = true; try { androidHttpTransport.call(SOAP_ACTION, envelope); SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn; System.out.println("Response::"+resultsRequestSOAP.toString()); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } return ""; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); } } 

It is no secret that working with any network activity should be done from a separate asynchronous task. doInBackground is the standard AsyncTask method. If you are not familiar yet, then here it is written about him simply and very clearly.

The MainActivity itself looks like this:

 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DataLoader dl = new DataLoader(); dl.execute(); } } 

At this adventure does not end there. In my case, the request to the server was closed by Basic Auth, so it was necessary to enter the login and password somewhere. And I haven’t found an unequivocal answer to this question on the Internet. In many articles, a certain class HttpTransportBasicAuthSE was mentioned, in the constructor of which a login with a password is passed. But it was not found in ksoap2-android, I had to search the Internet. Found here . I quote the full text:

 public class HttpTransportBasicAuthSE extends HttpTransportSE { private String username; private String password; /** * Constructor with username and password * * @param url * The url address of the webservice endpoint * @param username * Username for the Basic Authentication challenge RFC 2617 * @param password * Password for the Basic Authentication challenge RFC 2617 */ public HttpTransportBasicAuthSE(String url, String username, String password) { super(url); this.username = username; this.password = password; } public ServiceConnection getServiceConnection() throws IOException { ServiceConnectionSE midpConnection = new ServiceConnectionSE(url); addBasicAuthentication(midpConnection); return midpConnection; } protected void addBasicAuthentication(ServiceConnection midpConnection) throws IOException { if (username != null && password != null) { StringBuffer buf = new StringBuffer(username); buf.append(':').append(password); byte[] raw = buf.toString().getBytes(); buf.setLength(0); buf.append("Basic "); org.kobjects.base64.Base64.encode(raw, 0, raw.length, buf); midpConnection.setRequestProperty("Authorization", buf.toString()); } } } 

I suppose, comments to the code are superfluous. I’ll only clarify that in order to use HttpTransportBasicAuthSE, it’s enough just to change the line in the DataLoader

 HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); 

on

 HttpTransportBasicAuthSE androidHttpTransport = new HttpTransportBasicAuthSE(URL, "basicLogin", "authPassword"); 

and everything starts to work with authorization very clearly!

PS: do not forget to add permission to Internet to Manifest

 <uses-permission android:name="android.permission.INTERNET" /> 

Source: https://habr.com/ru/post/340642/


All Articles