Skip to content

Commit

Permalink
[BUGFIX] 9234 - WFS client doesn't expose Header Authorization
Browse files Browse the repository at this point in the history
Like for the others OGC providers: WMS and WCS, the user can set the
login and password to access to WFS protected data. But the QGIS WFS
provider doen't expose header authorization. It doesn't use login and
password.

This patch set header authorization for all WFS connexion if login and
password are set.
And I think this patch has to be backported to release_2-2, because QGIS
can't acces to protected WFS data.
  • Loading branch information
rldhont committed Apr 3, 2014
1 parent a43bd62 commit a98df93
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/core/qgsgml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ QgsGml::~QgsGml()
{
}

int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent )
int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent, const QString& userName, const QString& password )
{
mUri = uri;
mWkbType = wkbType;
Expand All @@ -79,6 +79,10 @@ int QgsGml::getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangl
mExtent.setMinimal();

QNetworkRequest request( mUri );
if ( !userName.isNull() || !password.isNull() )
{
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( userName ).arg( password ).toAscii().toBase64() );
}
QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );

connect( reply, SIGNAL( finished() ), this, SLOT( setFinished() ) );
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsgml.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class CORE_EXPORT QgsGml : public QObject
* @param extent retrieved extents
* @return 0 in case of success
*/
int getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent = 0 );
int getFeatures( const QString& uri, QGis::WkbType* wkbType, QgsRectangle* extent = 0, const QString& userName = QString(), const QString& password = QString() );

/** Read from GML data. Constructor uri param is ignored
* Supports only UTF-8, UTF-16, ISO-8859-1, ISO-8859-1 XML encodings.
Expand Down
18 changes: 18 additions & 0 deletions src/providers/wfs/qgswfscapabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,34 @@ QString QgsWFSCapabilities::uriGetFeature( QString typeName, QString crsString,

//add a wfs layer to the map
uri += "SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=" + typeName + crsString + bBoxString + filterString;

//add authorization information
if ( mUri.hasParam( "username" ) && mUri.hasParam( "password" ) )
{
uri += "&username="+mUri.param( "username" );
uri += "&password="+mUri.param( "password" );
}
QgsDebugMsg( uri );
return uri;
}

void QgsWFSCapabilities::setAuthorization( QNetworkRequest &request ) const
{
QgsDebugMsg( "entered" );
if ( mUri.hasParam( "username" ) && mUri.hasParam( "password" ) )
{
QgsDebugMsg( "setAuthorization " + mUri.param( "username" ) );
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( mUri.param( "username" ) ).arg( mUri.param( "password" ) ).toAscii().toBase64() );
}
}

void QgsWFSCapabilities::requestCapabilities()
{
mErrorCode = QgsWFSCapabilities::NoError;
mErrorMessage.clear();

QNetworkRequest request( uriGetCapabilities() );
setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
Expand All @@ -171,6 +188,7 @@ void QgsWFSCapabilities::capabilitiesReplyFinished()
{
QgsDebugMsg( "redirecting to " + redirect.toUrl().toString() );
QNetworkRequest request( redirect.toUrl() );
setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );

Expand Down
10 changes: 10 additions & 0 deletions src/providers/wfs/qgswfscapabilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define QGSWFSCAPABILITIES_H

#include <QObject>
#include <QNetworkRequest>

#include "qgsrectangle.h"
#include "qgsdatasourceuri.h"
Expand Down Expand Up @@ -72,6 +73,9 @@ class QgsWFSCapabilities : public QObject
//! return parsed capabilities - requestCapabilities() must be called before
GetCapabilities capabilities() { return mCaps; }

//! set authorization header
void setAuthorization( QNetworkRequest &request ) const;

signals:
void gotCapabilities();

Expand All @@ -90,6 +94,12 @@ class QgsWFSCapabilities : public QObject
GetCapabilities mCaps;
ErrorCode mErrorCode;
QString mErrorMessage;

//! Username for basic http authentication
QString mUserName;

//! Password for basic http authentication
QString mPassword;
};

#endif // QGSWFSCAPABILITIES_H
21 changes: 19 additions & 2 deletions src/providers/wfs/qgswfsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgswfsfeatureiterator.h"
#include "qgswfsprovider.h"
#include "qgsdatasourceuri.h"
#include "qgsspatialindex.h"
#include "qgslogger.h"
#include "qgsmessagelog.h"
Expand Down Expand Up @@ -89,6 +90,9 @@ QgsWFSProvider::QgsWFSProvider( const QString& uri )
mSourceCRS.createFromOgcWmsCrs( srsname );
}

mAuth.mUserName = parameterFromUrl( "username" );
mAuth.mPassword = parameterFromUrl( "password" );

//fetch attributes of layer and type of its geometry attribute
//WBC 111221: extracting geometry type here instead of getFeature allows successful
//layer creation even when no features are retrieved (due to, e.g., BBOX or FILTER)
Expand Down Expand Up @@ -682,7 +686,10 @@ int QgsWFSProvider::getFeatureGET( const QString& uri, const QString& geometryAt
}

//if ( dataReader.getWFSData() != 0 )
if ( dataReader.getFeatures( uri, &mWKBType, &mExtent ) != 0 )
QUrl getFeatureUrl( uri );
getFeatureUrl.removeQueryItem( "username" );
getFeatureUrl.removeQueryItem( "password" );
if ( dataReader.getFeatures( getFeatureUrl.toString(), &mWKBType, &mExtent, mAuth.mUserName, mAuth.mPassword ) != 0 )
{
QgsDebugMsg( "getWFSData returned with error" );
return 1;
Expand Down Expand Up @@ -751,10 +758,13 @@ int QgsWFSProvider::describeFeatureTypeGET( const QString& uri, QString& geometr
mNetworkRequestFinished = false;

QUrl describeFeatureUrl( uri );
describeFeatureUrl.removeQueryItem( "username" );
describeFeatureUrl.removeQueryItem( "password" );
describeFeatureUrl.removeQueryItem( "SRSNAME" );
describeFeatureUrl.removeQueryItem( "REQUEST" );
describeFeatureUrl.addQueryItem( "REQUEST", "DescribeFeatureType" );
QNetworkRequest request( describeFeatureUrl.toString() );
mAuth.setAuthorization( request );
QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );

connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
Expand Down Expand Up @@ -1338,6 +1348,8 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum
mNetworkRequestFinished = false;

QUrl typeDetectionUri( dataSourceUri() );
typeDetectionUri.removeQueryItem( "username" );
typeDetectionUri.removeQueryItem( "password" );
typeDetectionUri.removeQueryItem( "REQUEST" );
typeDetectionUri.removeQueryItem( "TYPENAME" );
typeDetectionUri.removeQueryItem( "BBOX" );
Expand All @@ -1349,6 +1361,7 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument& doc, QDomDocum
QString serverUrl = typeDetectionUri.toString();

QNetworkRequest request( serverUrl );
mAuth.setAuthorization( request );
request.setHeader( QNetworkRequest::ContentTypeHeader, "text/xml" );
QNetworkReply* reply = QgsNetworkAccessManager::instance()->post( request, doc.toByteArray( -1 ) );

Expand Down Expand Up @@ -1475,7 +1488,11 @@ void QgsWFSProvider::getLayerCapabilities()

QString uri = dataSourceUri();
uri.replace( QString( "GetFeature" ), QString( "GetCapabilities" ) );
QNetworkRequest request( uri );
QUrl getCapabilitiesUrl( uri );
getCapabilitiesUrl.removeQueryItem( "username" );
getCapabilitiesUrl.removeQueryItem( "password" );
QNetworkRequest request( getCapabilitiesUrl.toString() );
mAuth.setAuthorization( request );
QNetworkReply* reply = QgsNetworkAccessManager::instance()->get( request );

connect( reply, SIGNAL( finished() ), this, SLOT( networkRequestFinished() ) );
Expand Down
26 changes: 26 additions & 0 deletions src/providers/wfs/qgswfsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,32 @@
#include "qgsvectorlayer.h"
#include "qgswfsfeatureiterator.h"

#include <QNetworkRequest>

class QgsRectangle;
class QgsSpatialIndex;

// TODO: merge with QgsWmsAuthorization?
struct QgsWFSAuthorization
{
QgsWFSAuthorization( const QString& userName = QString(), const QString& password = QString() ) : mUserName( userName ), mPassword( password ) {}

//! set authorization header
void setAuthorization( QNetworkRequest &request ) const
{
if ( !mUserName.isNull() || !mPassword.isNull() )
{
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( mUserName ).arg( mPassword ).toAscii().toBase64() );
}
}

//! Username for basic http authentication
QString mUserName;

//! Password for basic http authentication
QString mPassword;
};

/**A provider reading features from a WFS server*/
class QgsWFSProvider: public QgsVectorDataProvider
{
Expand Down Expand Up @@ -130,6 +153,9 @@ class QgsWFSProvider: public QgsVectorDataProvider
private:
bool mNetworkRequestFinished;
friend class QgsWFSFeatureSource;

//! http authorization details
QgsWFSAuthorization mAuth;

protected:
/**Thematic attributes*/
Expand Down

0 comments on commit a98df93

Please sign in to comment.