Hi Rob, I'm in trouble with the basic authentication process ( I'm now using
ARQ 2.10.1 )
In one hand the Queries work like this :
when we calls one of the 4 method execX of a queryExecution, the
QueryEngineHTTP calls makeHttpQuery, and after few steps this code line is
executed :
httpConnection.setRequestProperty("Authorization", "Basic "+y) ;
where y contains userName:password 64Bits encrypted.
This make the http request header contains the Key, Value couple :
"Authorization" "Basic username:password".
I'm OK with this.
In the other hand, the update seem to handle Basic Authentication in a
different way.
I used this code :
UpdateRequest update =
UpdateFactory.create(queryString);
UpdateProcessRemoteForm exec = (UpdateProcessRemoteForm)
UpdateExecutionFactory.createRemoteForm(update, service);
exec.setAuthentication("[email protected]", "savaillon".toCharArray());
And I'm unable to retrieve the usename and the password.
Request contains following fields :
In headers :
content-lenght : 273
content-type : application/x-www-form-urlencoded; charset=UTF-8
host : localhost:8080
conection : Keep-Alive
user-agent: Apache-HttpClient/4.2.3 (java 1.5)
In params :
update : my update
No attribute.
I tried to follow in the ARQ library the path of my username and password, and
finally they transited to the applyAuthentication in HttpOp.
This method create a CredentialsProvider and set the credentials username and
password. But this method has a void return type, and I don't see any
communication point with the rest of the HttpOp code.
Do I missed something ?
VAÏSSE-LESTEVEN Arthur.
>I was using the 2.9.2 ARQ version. I'll update to 2.10.1.
>Thanks for your quick answer and for your work Rob!
>
>VAÏSSE-LESTEVEN Arthur.
>
>
>>What version of ARQ are you using?
>>
>>I put changes in place which went into the 2.10.1 release which should
>>permit easy HTTP auth on SPARQL updates. Both
>>UpdateExecutionFactory.createRemote() and
>>UpdateExecutionFactory.createRemoteForm() return an instance derived from
>>UpdateProcessRemoteBase which has a setAuthentication() method
>>
>>If you are using a version of ARQ prior to 2.10.0 there is no common base
>>class but both UpdateProcessRemote and UpdateProcessRemoteForm
would still
>>have a setHttpContext() method which allows you to pass in a HttpContext
>>which can be used to pass in authentication settings using the HttpClient
>>APIs. Even with 2.10.1 you can still choose to use this method
>>particularly if you need to pass complex credentials.
>>
>>Rob
>>
>>
>>On 6/18/13 8:10 AM, "Arthur Vaïsse-Lesteven" <[email protected]> wrote:
>>
>>>Hi,
>>>
>>>
>>>The remote execution of SPARQL queries offer the setBasicAuthentication
>>>fonctionality(1). I'm using it; and when I tried to use it with SPARQL
>>>Update it appears that SPARQL Update doesn't handle Authentication.
>>>I would like to know, do it exist any way to do the same thing in ARQ ? I
>>>writted some code by extending 2 apache classes, but it would be
better
>>>to just use the API. Do you intend to not allow basicAuthentification ?
>>>It is incompatible with http basic authentication ? There are only
>>>24hours per day and you don't had the time to do it yet ?
>>>
>>>Do this functionality is planed ?
>>>
>>>________________________________________________________________________
>>>
>>>(1) What i can write :
>>>
>>>[...]
>>>
>>>
>>>QueryEngineHTTP exec = (QueryEngineHTTP)
>>>QueryExecutionFactory.createServiceRequest(endpoint_URL, query);
>>>exec.setBasicAuthentication(user, password);
>>>
>>>exec.exec...
>>>
>>>[...]
>>>
>>>(2)What I want to write :
>>>
>>>[...]
>>>UpdateProcessRemote exec =
(UpdateProcessRemote)
>>>UpdateExecutionFactory.createRemote(update, endpoint_URL);
>>>exec.setBasicAuthentication(user, password);
>>>
>>>exec.excute();
>>>
>>>[...]
>>>
>>>
>>>
>>>I tried to custom the UpdateProcessRemote class to allow (2). This
>>>currently don't work on my computer, but it seem's to be due to a maven
>>>version conflict at level of HttpClient. This class must be compatible
>>>with current version of Jena.( I set my modifications in bold ).( also
>>>downlodable at : http://arthurvaisse.free.fr/classes/ )
>>>
>>>Thank you,
>>>VAÏSSE-LESTEVEN Arthur.
>>>
>>>
>>>________________________________________________________________________
>>>
>>>public class UpdateProcessRemote
implements UpdateProcessor{
>>>
>>> private String user = null ;
>>> private char[] password = null ;
>>>
>>> private final UpdateRequest request ;
>>> private final String endpoint ;
>>>
>>> public UpdateProcessRemote(UpdateRequest request , String endpoint )
>>> {
>>> this.request = request ;
>>> this.endpoint = endpoint ;
>>>
>>> }
>>>
>>> @Override
>>> public void setInitialBinding(QuerySolution binding)
>>> {
>>> throw new ARQException("Initial bindings
for a remote update
>>>execution request not supported") ;
>>> }
>>>
>>> @Override
>>> public GraphStore getGraphStore()
>>> {
>>> return null ;
>>> }
>>>
>>> @Override
>>> public void execute()
>>> {
>>> String reqStr = request.toString() ;
>>> HttpOpCustom.execHttpPost(endpoint,
>>>WebContent.contentTypeSPARQLUpdate, reqStr, user, password);
>>> }
>>>
>>> //comes from QueryEngineHTTP.
>>> public void
setBasicAuthentication(String user, char[] password)
>>>
>>> {
>>> this.user = user ;
>>> this.password = password ;
>>> }
>>>________________________________________________________________________
>>>
>>>I added this functions to HttpOp to create my custom HttpOp :
>>>
>>> //Just added credentials in parameters
>>> public static void execHttpPost(String url, String contentType,
>>>String content, String user, char[] password)
>>> {
>>> execHttpPost(url, contentType, content, null, null, user,
>>>password) ;
>>>
}
>>>
>>>
>>> //Just added credentials in parameters
>>> public static void execHttpPost(String url, String contentType,
>>>String content,
>>> String acceptType, Map<String, HttpResponseHandler> handlers,
>>> String user, char[] password)
>>> {
>>> StringEntity e = null ;
>>> try
>>> {
>>> e = new StringEntity(content, "UTF-8") ;
>>>
e.setContentType(contentType) ;
>>> execHttpPost(url, e, acceptType, handlers, user, password) ;
>>> } catch (UnsupportedEncodingException e1)
>>> {
>>> throw new ARQInternalErrorException("Platform does not
>>>support required UTF-8") ;
>>> } finally { closeEntity(e) ; }
>>> }
>>>
>>>
>>> public static void execHttpPost(String url, HttpEntity provider,
>>> String acceptType, Map<String, HttpResponseHandler>
handlers,
>>> String user, char[] password)
>>> {
>>> try {
>>> long id = counter.incrementAndGet() ;
>>> String requestURI = determineBaseIRI(url) ;
>>> String baseIRI = determineBaseIRI(requestURI) ;
>>>
>>> HttpPost httppost = new HttpPost(requestURI);
>>>
>>> if ( user != null || password !=
null){
>>> if(user==null || password == null){
>>> log.warn("Only one of user/password is set") ;
>>> }
>>> //this code come from httpQuery
>>> StringBuffer x = new StringBuffer() ;
>>> byte b[] =
>>>x.append(user).append(":").append(password).toString().getBytes("UTF-8")
;
>>> String y = Base64.encodeBase64String(b) ;
>>> //this single code line is mine
>>> httppost.addHeader("Authorization", "Basic "+y);
>>> }
>>> if ( log.isDebugEnabled() )
>>> log.debug(format("[%d] %s %s",id
>>>,httppost.getMethod(),httppost.getURI().toString())) ;
>>>
>>> if (
provider.getContentType() == null )
>>> log.debug(format("[%d] No content type")) ;
>>>
>>> // Execute
>>> HttpClient httpclient = new DefaultHttpClient();
>>> httppost.setEntity(provider) ;
>>> HttpResponse response = httpclient.execute(httppost) ;
>>> httpResponse(id, response, baseIRI, handlers) ;
>>>
>>>
httpclient.getConnectionManager().shutdown();
>>> } catch (IOException ex)
>>> {
>>> ex.printStackTrace(System.err) ;
>>> }
>>> finally { closeEntity(provider) ; }
>>> }