Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > авторизация(проверка сертификата) на своём сайте


Автор: GhoulZEA 29.9.2011, 06:38
Delphi 2010
 Делаю Web-сервер через idHTTPServer.
 Сейчас процесс авторизации выглядит так:
 Человек вставляет e-token, стучится на сайт. Сервер через IOHandler (TIdServerIOHandlerSSLOpenSSL) реагирует на событие и вызывает функцию OnVerifyPeer,
Код

function TForm1.sslOpenVerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth: Integer): Boolean;

 где проверяется отпечаток ключа. Если ключ нормальный и существует, то функция возвращает True и авторизация продолжается. Сервер в процедуре idHTTPServerCommandGet запрашивает логин и пароль
Код

if not (ARequestInfo.AuthExists)or(ARequestInfo.AuthExists) then ...

 Получается, что проверка сертификата оторвана от проверки логина и человек (у которого есть подлинный сертификат) может зайти под любым логином.
 Можно ли получить какой-либо идентификатор человека/сессии в sslOpenVerifyPeer, по которому можно будет однозначно опознать его в процедуре idHTTPServerCommandGet? К примеру IP?

Автор: ~FoX~ 30.9.2011, 23:10
Насколько я помню, однозначное опознавание, чаще всего, происходит по МАК адресу.... 

Автор: GhoulZEA 2.10.2011, 14:20
Да вся проблема в том, что процедура onVerifyPeer не получает ничего кроме сертификата. Т.е. в ней я однозначно могу сказать, что у такого-то сертификат в норме и разрешаю ему входить. А вот как после этого идентифицировать (и назначить права) человека в idHTTPserver не знаю :(

Автор: Drug51 15.11.2016, 12:26
Цитата(GhoulZEA @ 29.9.2011,  06:38)
Delphi 2010
 Делаю Web-сервер через idHTTPServer.
 Сейчас процесс авторизации выглядит так:
 Человек вставляет e-token, стучится на сайт. Сервер через IOHandler (TIdServerIOHandlerSSLOpenSSL) реагирует на событие и вызывает функцию OnVerifyPeer,
Код

function TForm1.sslOpenVerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth: Integer): Boolean;

 где проверяется отпечаток ключа. Если ключ нормальный и существует, то функция возвращает True и авторизация продолжается. Сервер в процедуре idHTTPServerCommandGet запрашивает логин и пароль
Код

if not (ARequestInfo.AuthExists)or(ARequestInfo.AuthExists) then ...

 Получается, что проверка сертификата оторвана от проверки логина и человек (у которого есть подлинный сертификат) может зайти под любым логином.
 Можно ли получить какой-либо идентификатор человека/сессии в sslOpenVerifyPeer, по которому можно будет однозначно опознать его в процедуре idHTTPServerCommandGet? К примеру IP?

Подскажите, решили ли проблему? И каким образом вы получаете отпечаток? можно по подробней о sslOpenVerifyPeer

Автор: GhoulZEA 15.11.2016, 18:31
Проблема более или менее была решена. Возможно не совсем правильно. По отпечатку ключа каждой персоне присваивался ip. А в CommandGet опрашивался ip и от этого уже работала.
А потом появилась другая smile Часть пользователей сидела за маршрутизатором и соответственно все они имели один внешний ip, но права должны были быть разными. Пришлось задействовать куки.
Правда уже прошло 5 лет и честно говоря я уже плохо помню что сделал. Из программы надёргал кусков.

Код

type
TIdSSLIOHandlerSocketOpenSSLA=class (TIdSSLIOHandlerSocketOpenSSL)
protected
  function DoVerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth: Integer): Boolean; override;//, AError
end;

TIdServerIOHandlerSSLOpenSSLA=class (TIdServerIOHandlerSSLOpenSSL)
    constructor Create(AOwner: TComponent);
    function Accept(ASocket: TIdSocketHandle; AListenerThread: TIdThread; AYarn: TIdYarn): TIdIOHandler; override;
    function VerifyPeerProc(Certificate: TIdX509; AOk: Boolean; ADepth: Integer): Boolean;//, AError
end;


Код

...
var
id2: TIdServerIOHandlerSSLOpenSSLA;
...


Код

constructor TIdServerIOHandlerSSLOpenSSLA.Create(AOwner: TComponent );
begin
  inherited Create(AOwner);
  OnVerifyPeer:=VerifyPeerProc;
end;

function TIdServerIOHandlerSSLOpenSSLA.VerifyPeerProc(Certificate: TIdX509; AOk: Boolean; ADepth: Integer): Boolean;//, AError
begin
  result:=true;
end;

function TIdServerIOHandlerSSLOpenSSLA.Accept(ASocket: TIdSocketHandle; AListenerThread: TIdThread; AYarn: TIdYarn): TIdIOHandler;
var
  LIO: TIdSSLIOHandlerSocketOpenSSLA;
  s: string;
begin
  Assert(ASocket<>nil);
  Assert(fSSLContext<>nil);
  LIO:=TIdSSLIOHandlerSocketOpenSSLA.Create(nil);
  LIO.PassThrough:=True;
  LIO.Open;
  if LIO.Binding.Accept(ASocket.Handle) then
  begin
    s:=LIO.Binding.PeerIP;
    FreeAndNil(LIO.fxSSLOptions);
    LIO.IsPeer:=True;
    LIO.fxSSLOptions:=fxSSLOptions;
    LIO.fSSLSocket:=TIdSSLSocket.Create(LIO);
    LIO.fSSLContext:=fSSLContext;
  end
  else FreeAndNil(LIO);
  Result:=LIO;
end;



Код

procedure TForm1.FormCreate(Sender: TObject);
...
// создаём хендлер ssl
  id2:=TIdServerIOHandlerSSLOpenSSLA.Create(self);
  IdHTTPServer.IOHandler:=id2;

  id2.SSLOptions.CertFile:='server.crt';
  id2.SSLOptions.KeyFile:='server.key';
  id2.SSLOptions.RootCertFile:='ca.crt';
  id2.SSLOptions.Method:=sslvTLSv1;//sslvSSLv3;
  id2.SSLOptions.Mode:=sslmBoth;
  id2.SSLOptions.VerifyDepth:=0;
  id2.SSLOptions.VerifyMode:=id2.SSLOptions.VerifyMode +[sslvrfPeer, sslvrfFailIfNoPeerCert, sslvrfClientOnce];
  id2.OnVerifyPeer:=IdSSLIOHandlerSocketOpenSSL1VerifyPeer;
...



Код

function TIdSSLIOHandlerSocketOpenSSLA.DoVerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth: Integer): Boolean;//, AError
var
  s,port: String;
...
  s:=self.binding.peerip;
  try
    port:=IntToStr(self.binding.PeerPort);
  except
    port:='0';
  end;
  L1:=Length(Certificate.Fingerprints.SHA1AsString);
  s:=Certificate.Fingerprints.SHA1AsString;
...


Код

procedure TForm1.idHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
...
RemoteIP:=ARequestInfo.RemoteIP;


Автор: Drug51 16.11.2016, 12:03
GhoulZEA, Спасибо за оперативный ответ! smile  Вы заставили меня копать дальше))) smile  и вот ответ на вопрос. Думаю тема закрыта. smile  smile  smile 

Код


procedure TForm1.IdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
    Log('Fingerprints.SHA1=%s',[TIdSSLIOHandlerSocketOpenSSL(AContext.Connection.IOHandler).SSLSocket.PeerCert.Fingerprints.SHA1AsString]);   
end;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)