add HTTP Basic Authorization to WS Client and Server

see: #55
This commit is contained in:
Markus Sattler
2016-02-17 17:56:03 +01:00
parent 2d87bfa3d6
commit c57a4c19ab
6 changed files with 106 additions and 2 deletions

View File

@ -77,6 +77,7 @@ void setup() {
}
webSocket.begin("192.168.0.123", 81);
//webSocket.setAuthorization("user", "Password"); // HTTP Basic Authorization
webSocket.onEvent(webSocketEvent);
}

View File

@ -180,6 +180,8 @@ typedef struct {
uint8_t cWsHeader[WEBSOCKETS_MAX_HEADER_SIZE]; ///< RX WS Message buffer
WSMessageHeader_t cWsHeaderDecode;
String base64Authorization; ///< Base64 encoded Auth request
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
String cHttpLine; ///< HTTP header lines
#endif

View File

@ -25,6 +25,7 @@
#include "WebSockets.h"
#include "WebSocketsClient.h"
WebSocketsClient::WebSocketsClient() {
_cbEvent = NULL;
_client.num = 0;
@ -60,6 +61,7 @@ void WebSocketsClient::begin(const char *host, uint16_t port, const char * url,
_client.cProtocol = protocol;
_client.cExtensions = "";
_client.cVersion = 0;
_client.base64Authorization = "";
#ifdef ESP8266
randomSeed(RANDOM_REG32);
@ -202,6 +204,30 @@ void WebSocketsClient::disconnect(void) {
}
}
/**
* set the Authorizatio for the http request
* @param user const char *
* @param password const char *
*/
void WebSocketsClient::setAuthorization(const char * user, const char * password) {
if(user && password) {
String auth = user;
auth += ":";
auth += password;
_client.base64Authorization = base64_encode((uint8_t *)auth.c_str(), auth.length());
}
}
/**
* set the Authorizatio for the http request
* @param auth const char * base64
*/
void WebSocketsClient::setAuthorization(const char * auth) {
if(auth) {
_client.base64Authorization = auth;
}
}
//#################################################################################
//#################################################################################
//#################################################################################
@ -374,6 +400,10 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
handshake += "Sec-WebSocket-Extensions: " + client->cExtensions + "\r\n";
}
if(client->base64Authorization.length() > 0) {
handshake += "Authorization: Basic " + client->base64Authorization + "\r\n";
}
handshake += "\r\n";
client->tcp->write(handshake.c_str(), handshake.length());

View File

@ -68,6 +68,9 @@ class WebSocketsClient: private WebSockets {
void disconnect(void);
void setAuthorization(const char * user, const char * password);
void setAuthorization(const char * auth);
protected:
String _host;
uint16_t _port;

View File

@ -80,6 +80,8 @@ void WebSocketsServer::begin(void) {
client->cIsUpgrade = false;
client->cIsWebsocket = false;
client->base64Authorization = "";
client->cWsRXsize = 0;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->cHttpLine = "";
@ -262,6 +264,32 @@ void WebSocketsServer::disconnect(uint8_t num) {
}
}
/**
* set the Authorizatio for the http request
* @param user const char *
* @param password const char *
*/
void WebSocketsServer::setAuthorization(const char * user, const char * password) {
if(user && password) {
String auth = user;
auth += ":";
auth += password;
_base64Authorization = base64_encode((uint8_t *)auth.c_str(), auth.length());
}
}
/**
* set the Authorizatio for the http request
* @param auth const char * base64
*/
void WebSocketsServer::setAuthorization(const char * auth) {
if(auth) {
_base64Authorization = auth;
}
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
/**
* get an IP for a client
@ -564,6 +592,8 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
client->cProtocol = headerValue;
} else if(headerName.equalsIgnoreCase("Sec-WebSocket-Extensions")) {
client->cExtensions = headerValue;
} else if(headerName.equalsIgnoreCase("Authorization")) {
client->base64Authorization = headerValue;
}
} else {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
@ -583,6 +613,7 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cProtocol: %s\n", client->num, client->cProtocol.c_str());
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cExtensions: %s\n", client->num, client->cExtensions.c_str());
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cVersion: %d\n", client->num, client->cVersion);
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - base64Authorization: %s\n", client->num, client->base64Authorization);
bool ok = (client->cIsUpgrade && client->cIsWebsocket);
@ -598,6 +629,20 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
}
}
if(_base64Authorization.length() > 0) {
if(client->base64Authorization.length() > 0) {
String auth = "Basic ";
auth += _base64Authorization;
if(auth != client->base64Authorization) {
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] HTTP Authorization failed!\n", client->num);
handleAuthorizationFailed(client);
return;
}
} else {
ok = false;
}
}
if(ok) {
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Websocket connection incoming.\n", client->num);

View File

@ -78,6 +78,9 @@ public:
void disconnect(void);
void disconnect(uint8_t num);
void setAuthorization(const char * user, const char * password);
void setAuthorization(const char * auth);
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
IPAddress remoteIP(uint8_t num);
#endif
@ -86,6 +89,7 @@ protected:
uint16_t _port;
String _origin;
String _protocol;
String _base64Authorization; ///< Base64 encoded Auth request
WEBSOCKETS_NETWORK_SERVER_CLASS * _server;
@ -109,8 +113,8 @@ protected:
/**
* called if a non Websocket connection is comming in.
* Note: can be overrided
* called if a non Websocket connection is coming in.
* Note: can be override
* @param client WSclient_t * ptr to the client struct
*/
virtual void handleNonWebsocketConnection(WSclient_t * client) {
@ -126,6 +130,25 @@ protected:
clientDisconnect(client);
}
/**
* called if a non Authorization connection is coming in.
* Note: can be override
* @param client WSclient_t * ptr to the client struct
*/
virtual void handleAuthorizationFailed(WSclient_t *client) {
client->tcp->write("HTTP/1.1 401 Unauthorized\r\n"
"Server: arduino-WebSocket-Server\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 45\r\n"
"Connection: close\r\n"
"Sec-WebSocket-Version: 13\r\n"
"WWW-Authenticate: Basic realm=\"WebSocket Server\""
"\r\n"
"This Websocket server requires Authorization!");
clientDisconnect(client);
}
/**
* called for sending a Event to the app
* @param num uint8_t