This commit is contained in:
Daniele Teti 2019-07-24 20:48:22 +02:00
parent 9b59fd6e44
commit 9470c85514
12 changed files with 47 additions and 28 deletions

View File

@ -164,7 +164,8 @@ end;
- Improved! New consts defined in `HTTP_STATUS` to better describe the http status response.
- Improved! Now Firebird RQL' SQLGenerator can include primary key in "createinsert" if not autogenerated.
- New! Added support for `TArray<String>` and `TArray<Integer>` in default json serializer (Thank you [Pedro Oliveira](https://github.com/pedrooliveira01))
- Improved! DMVCFramework now has 130+ unit tests that checks its funtionalities at every build!
- Improved JWT Standard Compliance! Thanks to [Vinicius Sanchez](https://github.com/viniciussanchez) for his work on [issue #241](https://github.com/danieleteti/delphimvcframework/issues/241)
- Improved! DMVCFramework now has 130+ unit tests that checks its funtionalities at each build!
- New Installation procedure! Just open the project group, build all and install the design-time package (which is `dmvcframeworkDT`)

View File

@ -55,12 +55,6 @@ resourcestring
sLineBreak +
'{$R *.res}' + sLineBreak +
sLineBreak +
'type' + sLineBreak +
' TDMVCParseAuthentication = class' + sLineBreak +
' public' + sLineBreak +
' class procedure OnParseAuthentication(AContext: TIdContext; const AAuthType, AAuthData: String; var VUsername,' + sLineBreak +
' VPassword: String; var VHandled: Boolean);' + sLineBreak +
' end;' + sLineBreak +
sLineBreak +
'procedure RunServer(APort: Integer);' + sLineBreak +
'var' + sLineBreak +
@ -97,7 +91,7 @@ resourcestring
sLineBreak +
' LServer := TIdHTTPWebBrokerBridge.Create(nil);' + sLineBreak +
' try' + sLineBreak +
' LServer.OnParseAuthentication := TDMVCParseAuthentication.OnParseAuthentication;' + sLineBreak +
' LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;' + sLineBreak +
' LServer.DefaultPort := APort;' + sLineBreak +
sLineBreak +
' { more info about MaxConnections' + sLineBreak +

View File

@ -30,7 +30,7 @@ procedure TAuthenticationSample.OnAuthentication(const AContext: TWebContext; co
UserRoles: TList<System.string>;
var IsValid: Boolean; const SessionData: TSessionData);
begin
IsValid := UserName.Equals(Password); // hey!, this is just a demo!!!
IsValid := (not UserName.IsEmpty) and UserName.Equals(Password); // hey!, this is just a demo!!!
if IsValid then
begin
if UserName = 'user_raise_exception' then

View File

@ -61,9 +61,9 @@ begin
'/login',
[TJWTCheckableClaim.ExpirationTime, TJWTCheckableClaim.NotBefore, TJWTCheckableClaim.IssuedAt],
300,
'Authorization',
'username',
'password'
TMVCJWTDefaults.AUTHORIZATION_HEADER,
TMVCJWTDefaults.USERNAME_HEADER,
TMVCJWTDefaults.PASSWORD_HEADER
));
end;

View File

@ -8,6 +8,7 @@ uses
System.SysUtils,
System.Variants,
System.Classes,
MVCFramework.Middleware.JWT,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
@ -62,7 +63,9 @@ begin
lClient.UseBasicAuthentication := False;
lClient.ReadTimeOut(0);
if not FJWT.IsEmpty then
lClient.RequestHeaders.Values['Authorization'] := 'bearer ' + FJWT;
begin
lClient.RequestHeaders.Values[TMVCJWTDefaults.AUTHORIZATION_HEADER] := 'Bearer ' + FJWT;
end;
lQueryStringParams := TStringList.Create;
try
lQueryStringParams.Values['firstname'] := 'Daniele';
@ -114,8 +117,8 @@ begin
try
lClient.ReadTimeOut(0);
lClient
.Header('username', 'user1')
.Header('password', 'user1');
.Header(TMVCJWTDefaults.USERNAME_HEADER, 'user1')
.Header(TMVCJWTDefaults.PASSWORD_HEADER, 'user1');
lRest := lClient.doPOST('/login', []);
if lRest.HasError then
begin

View File

@ -7,6 +7,7 @@ uses
System.SysUtils,
Winapi.Windows,
Winapi.ShellAPI,
MVCFramework.Commons,
Web.WebReq,
Web.WebBroker,
IdHTTPWebBrokerBridge,
@ -24,6 +25,7 @@ begin
Writeln(Format('Starting HTTP Server or port %d', [APort]));
LServer := TIdHTTPWebBrokerBridge.Create(nil);
try
LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
LServer.DefaultPort := APort;
LServer.Active := True;
Writeln('THIS SERVER USES JWT WITH LIVEVALIDITYWINDOWS FEATURE');

View File

@ -36,6 +36,7 @@ implementation
uses
MVCFramework.RESTClient,
MVCFramework.Middleware.JWT,
MVCFramework.SystemJSONUtils,
System.JSON,
System.NetEncoding;
@ -52,7 +53,7 @@ begin
try
lClient.ReadTimeOut(0);
if not FJWT.IsEmpty then
lClient.RequestHeaders.Values['Authentication'] := 'bearer ' + FJWT;
lClient.RequestHeaders.Values[TMVCJWTDefaults.AUTHORIZATION_HEADER] := 'Bearer ' + FJWT;
lQueryStringParams := TStringList.Create;
try
lQueryStringParams.Values['firstname'] := 'Daniele';
@ -68,10 +69,10 @@ begin
Memo2.Lines.Text := lResp.BodyAsString;
// NEW CODE
tokenNew := lResp.HeaderValue('Authentication');
if tokenNew.StartsWith('bearer', True) then
tokenNew := lResp.HeaderValue(TMVCJWTDefaults.AUTHORIZATION_HEADER);
if tokenNew.StartsWith('Bearer', True) then
begin
tokenNew := tokenNew.Remove(0, 'bearer'.Length).Trim;
tokenNew := tokenNew.Remove(0, 'Bearer'.Length).Trim;
tokenNew := TNetEncoding.URL.URLDecode(tokenNew).Trim;
JWT := tokenNew;
end; // END NEW CODE
@ -90,8 +91,8 @@ begin
try
lClient.ReadTimeOut(0);
lClient
.Header('jwtusername', 'user1')
.Header('jwtpassword', 'user1');
.Header(TMVCJWTDefaults.USERNAME_HEADER, 'user1')
.Header(TMVCJWTDefaults.PASSWORD_HEADER, 'user1');
lRest := lClient.doPOST('/login', []);
lJSON := TSystemJSON.StringAsJSONObject(lRest.BodyAsString);
try

View File

@ -113,7 +113,7 @@ begin
.RegisterTypeSerializer(TypeInfo(TNullableRecordAlias), TNullableAliasSerializer.Create);
// This line registers custom serializers for TBitmap, TPngImage (Only MSWindows) and TJPEGImage (Only MSWindows)
RegisterOptionalCustomTypesSerializers(DMVC.Serializers);
RegisterOptionalCustomTypesSerializersForJSON(DMVC.Serializers);
end;
end.

View File

@ -39,7 +39,7 @@ uses
// System.JSON,
Data.DB,
IdGlobal,
IdCoderMIME;
IdCoderMIME, IdContext;
{$I dmvcframeworkbuildconsts.inc}
@ -599,6 +599,14 @@ const
('224.0.0.0', '239.255.255.255'),
('240.0.0.0', '255.255.255.255'));
type
TMVCParseAuthentication = class
public
class procedure OnParseAuthentication(AContext: TIdContext; const AAuthType, AAuthData: String; var VUsername,
VPassword: String; var VHandled: Boolean);
end;
implementation
uses
@ -1260,6 +1268,13 @@ begin
end;
end;
class procedure TMVCParseAuthentication.OnParseAuthentication(AContext: TIdContext; const AAuthType, AAuthData: String; var VUsername,
VPassword: String; var VHandled: Boolean);
begin
VHandled := SameText(LowerCase(AAuthType), 'bearer');
end;
initialization
gLock := TObject.Create;

View File

@ -138,6 +138,7 @@ begin
FRaiseExceptionOnError := aRaiseExceptionOnError;
FURL := aURL;
FHTTP := THTTPClient.Create;
FHTTP.ResponseTimeout := MaxInt;
FHTTPRequestHeaders := nil;
SetOnReceiveResponse(nil)
.SetOnReceiveData(nil)

View File

@ -179,6 +179,8 @@ var
AuthHeader: string;
AuthToken: string;
ErrorMsg: string;
const
AUTH_SCHEMA = 'Bearer';
begin
// check if the resource is protected
FAuthenticationHandler.OnRequest(AContext, AControllerQualifiedClassName, AActionName, AuthRequired);
@ -202,11 +204,11 @@ begin
Exit;
end;
// retrieve the token from the "authentication bearer" header
// retrieve the token from the "authentication Bearer" header
AuthToken := '';
if AuthHeader.StartsWith('bearer', True) then
if AuthHeader.Substring(0, AUTH_SCHEMA.Length).ToLower = 'bearer' then
begin
AuthToken := AuthHeader.Remove(0, 'bearer'.Length).Trim;
AuthToken := AuthHeader.Remove(0, AUTH_SCHEMA.Length).Trim;
AuthToken := Trim(TNetEncoding.URL.Decode(AuthToken));
end;
@ -240,7 +242,7 @@ begin
if NeedsToBeExtended(JWTValue) then
begin
ExtendExpirationTime(JWTValue);
AContext.Response.SetCustomHeader(FAuthorizationHeaderName, 'bearer ' + JWTValue.GetToken);
AContext.Response.SetCustomHeader(FAuthorizationHeaderName, 'Bearer ' + JWTValue.GetToken);
end;
end;
AHandled := False

View File

@ -761,7 +761,7 @@ begin
FHTTP.HandleRedirects := True;
FHTTP.Request.CustomHeaders.FoldLines := False;
FHTTP.Request.BasicAuthentication := True;
FHTTP.Request.BasicAuthentication := False; //DT 2018/07/24
FSerializer := GetDefaultSerializer;
end;