>Is there any HTTP proxying/redirection involved in your setup?
No. The only proxy is the SPARQL proxy that I'm coding. It is based on the work 
of wimmic team ( http://wimmics.inria.fr/projects/shi3ld/ ).

This is my code :

The query engine Http add to the HTTP Header ("Authorization", "Basic 
<username>:<password>") where user informations are 64Bits encoded.
My test consist in sending request to the proxy ( no redirection involved, the 
user credentials check is done by the proxy ).
For the sparql queries ( SELECT/ASK/DESCRIBE/CONSTRUCT ) I use this code in 
order to extract credentials :

    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.codec.binary.StringUtils;
    
    protected String[] extractCredentials(HttpServletRequest req){
        String auth = req.getHeader("Authorization");
        if( auth == null || !(auth.toUpperCase().startsWith("BASIC")) ){return 
null;} 
        return this.decode(auth.substring(6)).split(":"); 
    }
    
    private String decode(String s) {
        return StringUtils.newStringUtf8(Base64.decodeBase64(s));
    }

The UpdateProcessRemoteForm don't add anything to header during my test. I do 
this :

    UpdateRequest update = UpdateFactory.create(queryString);    
    UpdateProcessRemoteForm exec = (UpdateProcessRemoteForm) 
UpdateExecutionFactory.createRemoteForm(update, service);
    exec.setAuthentication("[email protected]", "test".toCharArray());
    exec.execute();   

And as there is no header corresponding to the key "Authorization" my proxy 
send a 407 error ( authentication required ).

>>>>>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)

Maybe your code is working but work in an other way ?

VAISSE-LESTEVEN Arthur.

>I added simple basic auth support to Fuseki and wrote unit tests that
>verified that authentication is working correctly.
>
>It would be useful to know what error code/messages you get with the
>latest SNAPSHOTs?
>
>Is there any HTTP proxying/redirection involved in your setup?
>
>The applyAuthentication() code scopes provided credentials to the given
>service URI so if the server is responding with a 401 Unauthorized on a
>different URI from the original request then HTTP Client may be failing to
>attempt to pass any credentials at all in response to the servers
>challenge and simply bailing out and throwing up the 401 error
>
>Rob
>
>
>On 6/25/13 2:44 AM, "Arthur Vaïsse-Lesteven" <[email protected]> wrote:
>
>>
>>Hi again.
>>
>>It seems that the bug is still present. The HTTPheader not contains
>>basicAuthentification informations. What test did you do about the new
>>httpOp ? I may doing it in a wrong way :/
>>
>>After the debugged applyAuthentication in HttpOp, there is the following
>>line : "HttpResponse response = httpclient.execute(httppost,
>>httpContext);"
>>
>>And I think that the HttpClient.execute method doesn't use the
>>authentication information available in his Credential provider.
>>
>>Rob : "Don't forget you can always check out and do a mvn install locally"
>>Ho yes, I'll do that next time!
>>
>>VAÏSSE-LESTEVEN Arthur.
>>
>>
>>>Hmmm, that is a little weird
>>>
>>>I just forced a rebuild and the latest build does have the change in it,
>>>not sure what happened there. Sometimes the Apache build servers are
>>>just a little flaky.
>>>
>>>Don't forget you can always check out and do a mvn install locally
>>>
>>>Rob
>>>
>>>From: Arthur Vaïsse-Lesteven
>>><[email protected]<mailto:[email protected]>>
>>>Reply-To: "[email protected]<mailto:[email protected]>"
>>><[email protected]<mailto:[email protected]>>, Arthur
>>>Vaïsse-Lesteven <[email protected]<mailto:[email protected]>>
>>>Date: Monday, June 24, 2013 5:26 AM
>>>To: "[email protected]<mailto:[email protected]>"
>>><[email protected]<mailto:[email protected]>>
>>>Subject: Re: Tr : Basic Authentication for SPARQL Update
>>>
>>>Hi Rob,
>>>
>>>It's a little confusing.
>>>
>>>You modified the HttpOp class in the release number 34 on the maven repo
>>>[1], but this modification isn't present in the last version ( 38 ) as
>>>you can see in the java file joined to this mail.
>>>
>>>The add of "client.setCredentialsProvider(provider);" line 400 probably
>>>solve the problem but I'm not able to test it as it isn't present in the
>>>last released version of ARQ.
>>>
>>>( The trunk version of your SVN seems to contains this code too ).
>>>
>>>Thanks for your work.
>>>
>>>VAISSE-LESTEVEN Arthur.
>>>
>>>
>>>[1]
>>>https://repository.apache.org/content/repositories/snapshots/org/apache/j
>>>ena/jena-arq/2.10.2-SNAPSHOT/
>>>________________________________
>>>De : Rob Vesse <[email protected]<mailto:[email protected]>>
>>>À : "[email protected]<mailto:[email protected]>"
>>><[email protected]<mailto:[email protected]>>
>>>Envoyé le : Vendredi 21 juin 2013 19h35
>>>Objet : Re: Tr : Basic Authentication for SPARQL Update
>>>
>>>The latest SNAPSHOTS now have the fix, you may need to add -U to your mvn
>>>calls if you have recently updated SNAPSHOTs to get the very latest
>>>
>>>Please test and confirm whether this resolves the issue
>>>
>>>Rob
>>>
>>>
>>>On 6/21/13 9:13 AM, "Rob Vesse"
>>><[email protected]<mailto:[email protected]>> wrote:
>>>
>>>>Nice catch
>>>>
>>>>Yes I appear to have made an error, I never associated the created
>>>>credentials provider with the HTTP Client
>>>>
>>>>Filed as JENA-475 (https://issues.apache.org/jira/browse/JENA-475)
>>>>
>>>>I will commit a fix ASAP and you should be able to pick up a
>>>>2.10.2-SNAPSHOT build in a few hours with the fix, if you can test with
>>>>the snapshot and report if this resolves the issue that would be great.
>>>>
>>>>You can verify whether the fix has gone into the snapshots by looking at
>>>>https://builds.apache.org/job/Jena__Development_Test/changes and seeing
>>>>if
>>>>there is a build listed where the commit messages mention JENA-475
>>>>
>>>>Rob
>>>>
>>>>
>>>>
>>>>On 6/20/13 11:51 PM, "Arthur Vaïsse-Lesteven"
>>>><[email protected]<mailto:[email protected]>>
>>>>wrote:
>>>>
>>>>>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]<mailto:[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]<mailto:[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) ; }
>>>>>>>>    }

Reply via email to