mirror of
https://github.com/abapGit/abapGit.git
synced 2025-05-01 20:32:26 +08:00
digest http authentication now works
yay
This commit is contained in:
parent
42a918609e
commit
866b5e5404
|
@ -2,13 +2,61 @@
|
||||||
*& Include ZABAPGIT_HTTP
|
*& Include ZABAPGIT_HTTP
|
||||||
*&---------------------------------------------------------------------*
|
*&---------------------------------------------------------------------*
|
||||||
|
|
||||||
CLASS lcl_http_client DEFINITION FINAL.
|
CLASS lcl_http_digest DEFINITION FINAL.
|
||||||
|
|
||||||
PUBLIC SECTION.
|
PUBLIC SECTION.
|
||||||
|
METHODS:
|
||||||
|
constructor
|
||||||
|
IMPORTING
|
||||||
|
ii_client TYPE REF TO if_http_client
|
||||||
|
iv_username TYPE string
|
||||||
|
iv_password TYPE string,
|
||||||
|
run
|
||||||
|
IMPORTING
|
||||||
|
ii_client TYPE REF TO if_http_client.
|
||||||
|
|
||||||
|
PRIVATE SECTION.
|
||||||
|
DATA: mv_ha1 TYPE string,
|
||||||
|
mv_username TYPE string,
|
||||||
|
mv_realm TYPE string,
|
||||||
|
mv_qop TYPE string,
|
||||||
|
mv_nonce TYPE string.
|
||||||
|
|
||||||
|
CLASS-DATA: gv_nc TYPE n LENGTH 8.
|
||||||
|
|
||||||
|
CLASS-METHODS:
|
||||||
|
md5
|
||||||
|
IMPORTING
|
||||||
|
iv_data TYPE string
|
||||||
|
RETURNING
|
||||||
|
VALUE(rv_hash) TYPE string.
|
||||||
|
|
||||||
|
METHODS:
|
||||||
|
hash
|
||||||
|
IMPORTING
|
||||||
|
iv_qop TYPE string
|
||||||
|
iv_nonce TYPE string
|
||||||
|
iv_uri TYPE string
|
||||||
|
iv_method TYPE string
|
||||||
|
iv_cnonse TYPE string
|
||||||
|
RETURNING
|
||||||
|
VALUE(rv_response) TYPE string,
|
||||||
|
parse
|
||||||
|
IMPORTING
|
||||||
|
ii_client TYPE REF TO if_http_client.
|
||||||
|
|
||||||
|
ENDCLASS.
|
||||||
|
|
||||||
|
CLASS lcl_http_client DEFINITION FINAL.
|
||||||
|
|
||||||
|
PUBLIC SECTION.
|
||||||
|
|
||||||
METHODS:
|
METHODS:
|
||||||
constructor
|
constructor
|
||||||
IMPORTING ii_client TYPE REF TO if_http_client,
|
IMPORTING ii_client TYPE REF TO if_http_client,
|
||||||
close,
|
close,
|
||||||
|
set_digest
|
||||||
|
IMPORTING io_digest TYPE REF TO lcl_http_digest,
|
||||||
send_receive_close
|
send_receive_close
|
||||||
IMPORTING
|
IMPORTING
|
||||||
iv_data TYPE xstring
|
iv_data TYPE xstring
|
||||||
|
@ -27,7 +75,8 @@ CLASS lcl_http_client DEFINITION FINAL.
|
||||||
RAISING lcx_exception.
|
RAISING lcx_exception.
|
||||||
|
|
||||||
PROTECTED SECTION.
|
PROTECTED SECTION.
|
||||||
DATA: mi_client TYPE REF TO if_http_client.
|
DATA: mi_client TYPE REF TO if_http_client,
|
||||||
|
mo_digest TYPE REF TO lcl_http_digest.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
||||||
|
@ -37,6 +86,10 @@ CLASS lcl_http_client IMPLEMENTATION.
|
||||||
mi_client = ii_client.
|
mi_client = ii_client.
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
|
||||||
|
METHOD set_digest.
|
||||||
|
mo_digest = io_digest.
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
METHOD send_receive_close.
|
METHOD send_receive_close.
|
||||||
|
|
||||||
* do not use set_cdata as it modifies the Content-Type header field
|
* do not use set_cdata as it modifies the Content-Type header field
|
||||||
|
@ -85,6 +138,10 @@ CLASS lcl_http_client IMPLEMENTATION.
|
||||||
name = 'Accept'
|
name = 'Accept'
|
||||||
value = lv_value ). "#EC NOTEXT
|
value = lv_value ). "#EC NOTEXT
|
||||||
|
|
||||||
|
IF mo_digest IS BOUND.
|
||||||
|
mo_digest->run( mi_client ).
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
ENDMETHOD. "set_headers
|
ENDMETHOD. "set_headers
|
||||||
|
|
||||||
METHOD send_receive.
|
METHOD send_receive.
|
||||||
|
@ -149,87 +206,44 @@ CLASS lcl_http_client IMPLEMENTATION.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
||||||
CLASS lcl_http_digest DEFINITION FINAL.
|
|
||||||
|
|
||||||
PUBLIC SECTION.
|
|
||||||
CLASS-METHODS:
|
|
||||||
run
|
|
||||||
IMPORTING
|
|
||||||
ii_client TYPE REF TO if_http_client
|
|
||||||
iv_username TYPE string
|
|
||||||
iv_password TYPE string.
|
|
||||||
|
|
||||||
PRIVATE SECTION.
|
|
||||||
CLASS-DATA: gv_nc TYPE n LENGTH 8.
|
|
||||||
|
|
||||||
CLASS-METHODS:
|
|
||||||
parse
|
|
||||||
IMPORTING
|
|
||||||
iv_value TYPE string
|
|
||||||
EXPORTING
|
|
||||||
ev_scheme TYPE string
|
|
||||||
ev_realm TYPE string
|
|
||||||
ev_qop TYPE string
|
|
||||||
ev_nonce TYPE string,
|
|
||||||
md5
|
|
||||||
IMPORTING
|
|
||||||
iv_data TYPE string
|
|
||||||
RETURNING
|
|
||||||
VALUE(rv_hash) TYPE string,
|
|
||||||
hash
|
|
||||||
IMPORTING
|
|
||||||
iv_qop TYPE string
|
|
||||||
iv_realm TYPE string
|
|
||||||
iv_nonce TYPE string
|
|
||||||
iv_username TYPE clike
|
|
||||||
iv_uri TYPE string
|
|
||||||
iv_method TYPE string
|
|
||||||
iv_cnonse TYPE string
|
|
||||||
iv_password TYPE clike
|
|
||||||
RETURNING
|
|
||||||
VALUE(rv_response) TYPE string.
|
|
||||||
|
|
||||||
ENDCLASS.
|
|
||||||
|
|
||||||
CLASS lcl_http_digest IMPLEMENTATION.
|
CLASS lcl_http_digest IMPLEMENTATION.
|
||||||
|
|
||||||
|
METHOD constructor.
|
||||||
|
|
||||||
|
parse( ii_client ).
|
||||||
|
|
||||||
|
mv_ha1 = md5( |{ iv_username }:{ mv_realm }:{ iv_password }| ).
|
||||||
|
|
||||||
|
mv_username = iv_username.
|
||||||
|
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
METHOD hash.
|
METHOD hash.
|
||||||
|
|
||||||
DATA(lv_ha1) = md5( |{ iv_username }:{ iv_realm }:{ iv_password }| ).
|
DATA: lv_ha2 TYPE string.
|
||||||
DATA(lv_ha2) = md5( |{ iv_method }:{ iv_uri }| ).
|
|
||||||
|
|
||||||
rv_response = md5( |{ lv_ha1 }:{ iv_nonce }:{ gv_nc }:{ iv_cnonse }:{ iv_qop }:{ lv_ha2 }| ).
|
|
||||||
|
lv_ha2 = md5( |{ iv_method }:{ iv_uri }| ).
|
||||||
|
|
||||||
|
ASSERT NOT iv_cnonse IS INITIAL.
|
||||||
|
|
||||||
|
rv_response = md5( |{ mv_ha1 }:{ iv_nonce }:{ gv_nc }:{ iv_cnonse }:{ iv_qop }:{ lv_ha2 }| ).
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
|
||||||
METHOD run.
|
METHOD run.
|
||||||
|
|
||||||
DATA: lv_value TYPE string,
|
DATA: lv_value TYPE string,
|
||||||
lv_scheme TYPE string,
|
|
||||||
lv_realm TYPE string,
|
|
||||||
lv_response TYPE string,
|
lv_response TYPE string,
|
||||||
lv_method TYPE string,
|
lv_method TYPE string,
|
||||||
lv_uri TYPE string,
|
|
||||||
lv_auth TYPE string,
|
|
||||||
lv_cnonce TYPE string,
|
lv_cnonce TYPE string,
|
||||||
lv_qop TYPE string,
|
lv_uri TYPE string,
|
||||||
lv_nonce TYPE string.
|
lv_auth TYPE string.
|
||||||
|
|
||||||
|
|
||||||
lv_value = ii_client->response->get_header_field( 'www-authenticate' ).
|
ASSERT NOT mv_nonce IS INITIAL.
|
||||||
|
|
||||||
parse(
|
lv_method = ii_client->request->get_header_field( '~request_method' ).
|
||||||
EXPORTING
|
|
||||||
iv_value = lv_value
|
|
||||||
IMPORTING
|
|
||||||
ev_scheme = lv_scheme
|
|
||||||
ev_realm = lv_realm
|
|
||||||
ev_qop = lv_qop
|
|
||||||
ev_nonce = lv_nonce ).
|
|
||||||
|
|
||||||
ASSERT NOT lv_nonce IS INITIAL.
|
|
||||||
|
|
||||||
lv_method = 'GET'.
|
|
||||||
lv_uri = ii_client->request->get_header_field( '~request_uri' ).
|
lv_uri = ii_client->request->get_header_field( '~request_uri' ).
|
||||||
|
|
||||||
CALL FUNCTION 'GENERAL_GET_RANDOM_STRING'
|
CALL FUNCTION 'GENERAL_GET_RANDOM_STRING'
|
||||||
|
@ -239,21 +253,18 @@ CLASS lcl_http_digest IMPLEMENTATION.
|
||||||
random_string = lv_cnonce.
|
random_string = lv_cnonce.
|
||||||
|
|
||||||
lv_response = hash(
|
lv_response = hash(
|
||||||
iv_qop = lv_qop
|
iv_qop = mv_qop
|
||||||
iv_realm = lv_realm
|
iv_nonce = mv_nonce
|
||||||
iv_nonce = lv_nonce
|
|
||||||
iv_username = iv_username
|
|
||||||
iv_uri = lv_uri
|
iv_uri = lv_uri
|
||||||
iv_method = lv_method
|
iv_method = lv_method
|
||||||
iv_cnonse = lv_cnonce
|
iv_cnonse = lv_cnonce ).
|
||||||
iv_password = iv_password ).
|
|
||||||
|
|
||||||
* client response
|
* client response
|
||||||
lv_auth = |Digest username="{ iv_username
|
lv_auth = |Digest username="{ mv_username
|
||||||
}", realm="{ lv_realm
|
}", realm="{ mv_realm
|
||||||
}", nonce="{ lv_nonce
|
}", nonce="{ mv_nonce
|
||||||
}", uri="{ lv_uri
|
}", uri="{ lv_uri
|
||||||
}", qop={ lv_qop
|
}", qop={ mv_qop
|
||||||
}, nc={ gv_nc
|
}, nc={ gv_nc
|
||||||
}, cnonce="{ lv_cnonce
|
}, cnonce="{ lv_cnonce
|
||||||
}", response="{ lv_response }"|.
|
}", response="{ lv_response }"|.
|
||||||
|
@ -266,15 +277,14 @@ CLASS lcl_http_digest IMPLEMENTATION.
|
||||||
|
|
||||||
METHOD parse.
|
METHOD parse.
|
||||||
|
|
||||||
CLEAR: ev_scheme,
|
DATA: lv_value TYPE string.
|
||||||
ev_realm,
|
|
||||||
ev_qop,
|
|
||||||
ev_nonce.
|
|
||||||
|
|
||||||
FIND REGEX '^(\w+)' IN iv_value SUBMATCHES ev_scheme.
|
|
||||||
FIND REGEX 'realm="([\w ]+)"' IN iv_value SUBMATCHES ev_realm.
|
lv_value = ii_client->response->get_header_field( 'www-authenticate' ).
|
||||||
FIND REGEX 'qop="(\w+)"' IN iv_value SUBMATCHES ev_qop.
|
|
||||||
FIND REGEX 'nonce="([\w=/+\$]+)"' IN iv_value SUBMATCHES ev_nonce.
|
FIND REGEX 'realm="([\w ]+)"' IN lv_value SUBMATCHES mv_realm.
|
||||||
|
FIND REGEX 'qop="(\w+)"' IN lv_value SUBMATCHES mv_qop.
|
||||||
|
FIND REGEX 'nonce="([\w=/+\$]+)"' IN lv_value SUBMATCHES mv_nonce.
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
|
||||||
|
@ -311,6 +321,10 @@ ENDCLASS.
|
||||||
CLASS lcl_http DEFINITION FINAL.
|
CLASS lcl_http DEFINITION FINAL.
|
||||||
|
|
||||||
PUBLIC SECTION.
|
PUBLIC SECTION.
|
||||||
|
CONSTANTS: BEGIN OF gc_scheme,
|
||||||
|
digest TYPE string VALUE 'Digest',
|
||||||
|
END OF gc_scheme.
|
||||||
|
|
||||||
CLASS-METHODS:
|
CLASS-METHODS:
|
||||||
get_agent
|
get_agent
|
||||||
RETURNING VALUE(rv_agent) TYPE string,
|
RETURNING VALUE(rv_agent) TYPE string,
|
||||||
|
@ -331,7 +345,9 @@ CLASS lcl_http DEFINITION FINAL.
|
||||||
RETURNING VALUE(rv_bool) TYPE abap_bool,
|
RETURNING VALUE(rv_bool) TYPE abap_bool,
|
||||||
acquire_login_details
|
acquire_login_details
|
||||||
IMPORTING ii_client TYPE REF TO if_http_client
|
IMPORTING ii_client TYPE REF TO if_http_client
|
||||||
|
io_client TYPE REF TO lcl_http_client
|
||||||
iv_url TYPE string
|
iv_url TYPE string
|
||||||
|
RETURNING VALUE(rv_scheme) TYPE string
|
||||||
RAISING lcx_exception.
|
RAISING lcx_exception.
|
||||||
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
@ -348,7 +364,7 @@ CLASS lcl_http IMPLEMENTATION.
|
||||||
METHOD create_by_url.
|
METHOD create_by_url.
|
||||||
|
|
||||||
DATA: lv_uri TYPE string,
|
DATA: lv_uri TYPE string,
|
||||||
lv_expect_potentual_auth TYPE abap_bool,
|
lv_scheme TYPE string,
|
||||||
li_client TYPE REF TO if_http_client,
|
li_client TYPE REF TO if_http_client,
|
||||||
lo_settings TYPE REF TO lcl_settings.
|
lo_settings TYPE REF TO lcl_settings.
|
||||||
|
|
||||||
|
@ -395,14 +411,17 @@ CLASS lcl_http IMPLEMENTATION.
|
||||||
|
|
||||||
ro_client->send_receive( ).
|
ro_client->send_receive( ).
|
||||||
IF check_auth_requested( li_client ) = abap_true.
|
IF check_auth_requested( li_client ) = abap_true.
|
||||||
acquire_login_details( ii_client = li_client
|
lv_scheme = acquire_login_details( ii_client = li_client
|
||||||
|
io_client = ro_client
|
||||||
iv_url = iv_url ).
|
iv_url = iv_url ).
|
||||||
ro_client->send_receive( ).
|
ro_client->send_receive( ).
|
||||||
ENDIF.
|
ENDIF.
|
||||||
ro_client->check_http_200( ).
|
ro_client->check_http_200( ).
|
||||||
|
|
||||||
|
IF lv_scheme <> gc_scheme-digest.
|
||||||
lcl_login_manager=>save( iv_uri = iv_url
|
lcl_login_manager=>save( iv_uri = iv_url
|
||||||
ii_client = li_client ).
|
ii_client = li_client ).
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
|
||||||
|
@ -448,9 +467,9 @@ CLASS lcl_http IMPLEMENTATION.
|
||||||
METHOD acquire_login_details.
|
METHOD acquire_login_details.
|
||||||
|
|
||||||
DATA: lv_default_user TYPE string,
|
DATA: lv_default_user TYPE string,
|
||||||
lv_scheme TYPE string,
|
|
||||||
lv_user TYPE string,
|
lv_user TYPE string,
|
||||||
lv_pass TYPE string.
|
lv_pass TYPE string,
|
||||||
|
lo_digest TYPE REF TO lcl_http_digest.
|
||||||
|
|
||||||
|
|
||||||
lv_default_user = lcl_app=>user( )->get_repo_username( iv_url ).
|
lv_default_user = lcl_app=>user( )->get_repo_username( iv_url ).
|
||||||
|
@ -472,17 +491,20 @@ CLASS lcl_http IMPLEMENTATION.
|
||||||
iv_username = lv_user ).
|
iv_username = lv_user ).
|
||||||
ENDIF.
|
ENDIF.
|
||||||
|
|
||||||
lv_scheme = ii_client->response->get_header_field( 'www-authenticate' ).
|
rv_scheme = ii_client->response->get_header_field( 'www-authenticate' ).
|
||||||
FIND REGEX '^(\w+)' IN lv_scheme SUBMATCHES lv_scheme.
|
FIND REGEX '^(\w+)' IN rv_scheme SUBMATCHES rv_scheme.
|
||||||
|
|
||||||
CASE lv_scheme.
|
CASE rv_scheme.
|
||||||
WHEN 'Digest'.
|
WHEN gc_scheme-digest.
|
||||||
* https://en.wikipedia.org/wiki/Digest_access_authentication
|
* https://en.wikipedia.org/wiki/Digest_access_authentication
|
||||||
* eg used by https://www.gerritcodereview.com/
|
* e.g. used by https://www.gerritcodereview.com/
|
||||||
lcl_http_digest=>run(
|
CREATE OBJECT lo_digest
|
||||||
|
EXPORTING
|
||||||
ii_client = ii_client
|
ii_client = ii_client
|
||||||
iv_username = lv_user
|
iv_username = lv_user
|
||||||
iv_password = lv_pass ).
|
iv_password = lv_pass.
|
||||||
|
lo_digest->run( ii_client ).
|
||||||
|
io_client->set_digest( lo_digest ).
|
||||||
WHEN OTHERS.
|
WHEN OTHERS.
|
||||||
* https://en.wikipedia.org/wiki/Basic_access_authentication
|
* https://en.wikipedia.org/wiki/Basic_access_authentication
|
||||||
ii_client->authenticate(
|
ii_client->authenticate(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user