对特定应用程序的文件权限
File permission to a specific application
我在 Delphi 提出了申请,它是 运行ning Windows Server 2019 每个用户。这些用户通过远程桌面连接到用户会话(组策略)和 运行 应用程序。
是否可以在共享网络地图上打开配置文件只能使用我的应用程序而不是例如记事本?
更一般。存储实际上对用户保密的配置数据的最佳方式是什么?我正在考虑将敏感数据放在数据库中,但仍然很好,例如服务器信息不放在配置文件中而不是“烘焙”中。
这是我的第一个 post 我知道它介于编程和服务器配置之间。否则我的翻译比例似乎不会因为“只有应用程序打开文件”而受到打击。如果这个 post 不完美,请原谅。
我看到了几种可能性:
1°
如果您不想让用户“看到”您的数据,那么您必须对文件内容进行加密。有很多 Delphi encryption/decryption 库。我建议您从 Delphi Encryption Compendium 开始,它在 GitHub.
上免费提供
您可以将数据存储在内存结构中,例如 XML or JSON(Delphi 有内置例程来处理 XML 和 JSON) .在写入光盘之前,您对其进行加密,并在重新加载加密文件后,在以标准方式访问它之前对其进行解密。
2° 使用可从另一个帐户访问的文件,并让您的程序在需要访问该文件时模拟该帐户。
我写了一些代码来简化和演示这种方式。我创建了一个 class TImpersonateUser
有两个方法 Logon
和 Logoff
这将使程序连接到给定的用户帐户并断开连接。
要进行测试,首先使用另一个帐户登录并在某处创建一个文件,例如在文档中。然后登录回您的普通用户代码并启动演示程序(下面的代码)。填写用户名、域和密码(对于域,“.”将仅在本地计算机上进行身份验证)。使用您之前创建的文件的完整路径填写文件名。单击“文件访问”。它应该回答“找不到文件”。然后单击“模拟”,然后再次单击“文件访问”。现在您应该可以访问其他帐户中的文件。单击“还原为自我”并重试“文件访问”,它应该会再次失败。
综上所述,对于您的问题,用户看不到的数据必须在另一个帐户下创建,并且您的应用程序在需要访问数据时模拟另一个帐户。不要忘记在您的程序中以某种方式隐藏用户名和密码。
注意:获得句柄(打开的文件或流)后,您可以 RevertToSelf 并仍然使用句柄(或流)。它保持安全上下文(使用的帐户)直到关闭。这意味着您可以在打开文件前调用登录,打开后立即调用注销(或打开失败)并继续访问文件。
编辑: 我写了一个 blog post with more code.
unit ImpersonateUser;
interface
uses
Winapi.Windows, System.Classes;
const
LOGON32_LOGON_NEW_CREDENTIALS = 9; // Missing in Delphi
type
TImpersonateUser = class(TComponent)
protected
FUserToken : THandle;
FErrorCode : DWORD;
public
destructor Destroy; override;
function Logon(const UserName : String;
const Domain : String;
const Password : String) : Boolean;
procedure Logoff();
property ErrorCode : DWORD read FErrorCode;
end;
implementation
{ TImpersonateUser }
destructor TImpersonateUser.Destroy;
begin
if FUserToken <> 0 then begin
CloseHandle(FUserToken);
FUserToken := 0;
end;
inherited Destroy;
end;
procedure TImpersonateUser.Logoff;
begin
if FUserToken <> 0 then begin
RevertToSelf(); // Revert to our user
CloseHandle(FUserToken);
FUserToken := 0;
end;
end;
function TImpersonateUser.Logon(
const UserName : String;
const Domain : String;
const Password : String): Boolean;
var
LoggedOn : Boolean;
begin
Result := FALSE;
if FUserToken <> 0 then
Logoff();
if UserName = '' then begin // Must at least provide a user name
FErrorCode := ERROR_BAD_ARGUMENTS;
Exit;
end;
if Domain <> '' then
LoggedOn := LogonUser(PChar(UserName),
PChar(Domain),
PChar(Password),
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
FUserToken)
else
LoggedOn := LogonUser(PChar(UserName),
PChar(Domain),
PChar(Password),
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_WINNT50,
FUserToken);
if not LoggedOn then begin
FErrorCode := GetLastError();
Exit;
end;
if not ImpersonateLoggedOnUser(FUserToken) then begin
FErrorCode := GetLastError();
Exit;
end;
FErrorCode := S_OK;
Result := TRUE;
end;
end.
简单演示:
unit ImpersonateUserDemoMain;
interface
uses
Winapi.Windows, Winapi.Messages,
System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
ImpersonateUser;
type
TImpersonateUserMainForm = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
UserNameEdit: TEdit;
DomainEdit: TEdit;
PasswordEdit: TEdit;
ImpersonateButton: TButton;
Label4: TLabel;
FileNameEdit: TEdit;
RevertToSelfButton: TButton;
FileAccessButton: TButton;
procedure FileAccessButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ImpersonateButtonClick(Sender: TObject);
procedure RevertToSelfButtonClick(Sender: TObject);
private
FImpersonate : TImpersonateUser;
end;
var
ImpersonateUserMainForm: TImpersonateUserMainForm;
implementation
{$R *.dfm}
procedure TImpersonateUserMainForm.FileAccessButtonClick(Sender: TObject);
var
Stream : TFileStream;
begin
try
if not FileExists(FileNameEdit.Text) then
ShowMessage('File not found')
else begin
Stream := TFileStream.Create(FileNameEdit.Text, fmOpenRead);
try
ShowMessage('File opened');
finally
Stream.Free;
end;
end;
except
on E:Exception do
ShowMessage(E.Classname + ': ' + E.Message);
end;
end;
procedure TImpersonateUserMainForm.FormCreate(Sender: TObject);
begin
UserNameEdit.Text := 'YourUsername';
DomainEdit.Text := '.';
PasswordEdit.Text := 'YourPassword';
FilenameEdit.Text := 'C:\Users\AnotherUser\Documents\HelloWorld.txt';
FImpersonate := TImpersonateUser.Create(Self);
end;
procedure TImpersonateUserMainForm.ImpersonateButtonClick(Sender: TObject);
begin
if not FImpersonate.Logon(UserNameEdit.Text,
DomainEdit.Text,
PasswordEdit.Text) then begin
ShowMessage(Format('Failed with error 0x%X', [FImpersonate.ErrorCode]));
end
else
ShowMessage('Logon OK');
end;
procedure TImpersonateUserMainForm.RevertToSelfButtonClick(Sender: TObject);
begin
FImpersonate.Logoff;
ShowMessage('Reverted to self');
end;
end.
DFM 文件:
object ImpersonateUserMainForm: TImpersonateUserMainForm
Left = 0
Top = 0
Caption = 'ImpersonateUserMainForm'
ClientHeight = 142
ClientWidth = 331
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 16
Top = 20
Width = 49
Height = 13
Caption = 'UserName'
end
object Label2: TLabel
Left = 16
Top = 48
Width = 35
Height = 13
Caption = 'Domain'
end
object Label3: TLabel
Left = 12
Top = 76
Width = 46
Height = 13
Caption = 'Password'
end
object Label4: TLabel
Left = 16
Top = 104
Width = 16
Height = 13
Caption = 'File'
end
object UserNameEdit: TEdit
Left = 80
Top = 16
Width = 121
Height = 21
TabOrder = 0
Text = 'UserNameEdit'
end
object DomainEdit: TEdit
Left = 80
Top = 44
Width = 121
Height = 21
TabOrder = 1
Text = 'DomainEdit'
end
object PasswordEdit: TEdit
Left = 80
Top = 72
Width = 121
Height = 21
TabOrder = 2
Text = 'PasswordEdit'
end
object ImpersonateButton: TButton
Left = 232
Top = 14
Width = 75
Height = 25
Caption = 'Impersonate'
TabOrder = 3
OnClick = ImpersonateButtonClick
end
object FileNameEdit: TEdit
Left = 80
Top = 99
Width = 121
Height = 21
TabOrder = 4
Text = 'FileNameEdit'
end
object RevertToSelfButton: TButton
Left = 232
Top = 45
Width = 75
Height = 25
Caption = 'Revert to self'
TabOrder = 5
OnClick = RevertToSelfButtonClick
end
object FileAccessButton: TButton
Left = 232
Top = 76
Width = 75
Height = 25
Caption = 'File access'
TabOrder = 6
OnClick = FileAccessButtonClick
end
end
我在 Delphi 提出了申请,它是 运行ning Windows Server 2019 每个用户。这些用户通过远程桌面连接到用户会话(组策略)和 运行 应用程序。
是否可以在共享网络地图上打开配置文件只能使用我的应用程序而不是例如记事本?
更一般。存储实际上对用户保密的配置数据的最佳方式是什么?我正在考虑将敏感数据放在数据库中,但仍然很好,例如服务器信息不放在配置文件中而不是“烘焙”中。
这是我的第一个 post 我知道它介于编程和服务器配置之间。否则我的翻译比例似乎不会因为“只有应用程序打开文件”而受到打击。如果这个 post 不完美,请原谅。
我看到了几种可能性:
1° 如果您不想让用户“看到”您的数据,那么您必须对文件内容进行加密。有很多 Delphi encryption/decryption 库。我建议您从 Delphi Encryption Compendium 开始,它在 GitHub.
上免费提供您可以将数据存储在内存结构中,例如 XML or JSON(Delphi 有内置例程来处理 XML 和 JSON) .在写入光盘之前,您对其进行加密,并在重新加载加密文件后,在以标准方式访问它之前对其进行解密。
2° 使用可从另一个帐户访问的文件,并让您的程序在需要访问该文件时模拟该帐户。
我写了一些代码来简化和演示这种方式。我创建了一个 class TImpersonateUser
有两个方法 Logon
和 Logoff
这将使程序连接到给定的用户帐户并断开连接。
要进行测试,首先使用另一个帐户登录并在某处创建一个文件,例如在文档中。然后登录回您的普通用户代码并启动演示程序(下面的代码)。填写用户名、域和密码(对于域,“.”将仅在本地计算机上进行身份验证)。使用您之前创建的文件的完整路径填写文件名。单击“文件访问”。它应该回答“找不到文件”。然后单击“模拟”,然后再次单击“文件访问”。现在您应该可以访问其他帐户中的文件。单击“还原为自我”并重试“文件访问”,它应该会再次失败。
综上所述,对于您的问题,用户看不到的数据必须在另一个帐户下创建,并且您的应用程序在需要访问数据时模拟另一个帐户。不要忘记在您的程序中以某种方式隐藏用户名和密码。
注意:获得句柄(打开的文件或流)后,您可以 RevertToSelf 并仍然使用句柄(或流)。它保持安全上下文(使用的帐户)直到关闭。这意味着您可以在打开文件前调用登录,打开后立即调用注销(或打开失败)并继续访问文件。
编辑: 我写了一个 blog post with more code.
unit ImpersonateUser;
interface
uses
Winapi.Windows, System.Classes;
const
LOGON32_LOGON_NEW_CREDENTIALS = 9; // Missing in Delphi
type
TImpersonateUser = class(TComponent)
protected
FUserToken : THandle;
FErrorCode : DWORD;
public
destructor Destroy; override;
function Logon(const UserName : String;
const Domain : String;
const Password : String) : Boolean;
procedure Logoff();
property ErrorCode : DWORD read FErrorCode;
end;
implementation
{ TImpersonateUser }
destructor TImpersonateUser.Destroy;
begin
if FUserToken <> 0 then begin
CloseHandle(FUserToken);
FUserToken := 0;
end;
inherited Destroy;
end;
procedure TImpersonateUser.Logoff;
begin
if FUserToken <> 0 then begin
RevertToSelf(); // Revert to our user
CloseHandle(FUserToken);
FUserToken := 0;
end;
end;
function TImpersonateUser.Logon(
const UserName : String;
const Domain : String;
const Password : String): Boolean;
var
LoggedOn : Boolean;
begin
Result := FALSE;
if FUserToken <> 0 then
Logoff();
if UserName = '' then begin // Must at least provide a user name
FErrorCode := ERROR_BAD_ARGUMENTS;
Exit;
end;
if Domain <> '' then
LoggedOn := LogonUser(PChar(UserName),
PChar(Domain),
PChar(Password),
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
FUserToken)
else
LoggedOn := LogonUser(PChar(UserName),
PChar(Domain),
PChar(Password),
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_WINNT50,
FUserToken);
if not LoggedOn then begin
FErrorCode := GetLastError();
Exit;
end;
if not ImpersonateLoggedOnUser(FUserToken) then begin
FErrorCode := GetLastError();
Exit;
end;
FErrorCode := S_OK;
Result := TRUE;
end;
end.
简单演示:
unit ImpersonateUserDemoMain;
interface
uses
Winapi.Windows, Winapi.Messages,
System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
ImpersonateUser;
type
TImpersonateUserMainForm = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
UserNameEdit: TEdit;
DomainEdit: TEdit;
PasswordEdit: TEdit;
ImpersonateButton: TButton;
Label4: TLabel;
FileNameEdit: TEdit;
RevertToSelfButton: TButton;
FileAccessButton: TButton;
procedure FileAccessButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ImpersonateButtonClick(Sender: TObject);
procedure RevertToSelfButtonClick(Sender: TObject);
private
FImpersonate : TImpersonateUser;
end;
var
ImpersonateUserMainForm: TImpersonateUserMainForm;
implementation
{$R *.dfm}
procedure TImpersonateUserMainForm.FileAccessButtonClick(Sender: TObject);
var
Stream : TFileStream;
begin
try
if not FileExists(FileNameEdit.Text) then
ShowMessage('File not found')
else begin
Stream := TFileStream.Create(FileNameEdit.Text, fmOpenRead);
try
ShowMessage('File opened');
finally
Stream.Free;
end;
end;
except
on E:Exception do
ShowMessage(E.Classname + ': ' + E.Message);
end;
end;
procedure TImpersonateUserMainForm.FormCreate(Sender: TObject);
begin
UserNameEdit.Text := 'YourUsername';
DomainEdit.Text := '.';
PasswordEdit.Text := 'YourPassword';
FilenameEdit.Text := 'C:\Users\AnotherUser\Documents\HelloWorld.txt';
FImpersonate := TImpersonateUser.Create(Self);
end;
procedure TImpersonateUserMainForm.ImpersonateButtonClick(Sender: TObject);
begin
if not FImpersonate.Logon(UserNameEdit.Text,
DomainEdit.Text,
PasswordEdit.Text) then begin
ShowMessage(Format('Failed with error 0x%X', [FImpersonate.ErrorCode]));
end
else
ShowMessage('Logon OK');
end;
procedure TImpersonateUserMainForm.RevertToSelfButtonClick(Sender: TObject);
begin
FImpersonate.Logoff;
ShowMessage('Reverted to self');
end;
end.
DFM 文件:
object ImpersonateUserMainForm: TImpersonateUserMainForm
Left = 0
Top = 0
Caption = 'ImpersonateUserMainForm'
ClientHeight = 142
ClientWidth = 331
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 16
Top = 20
Width = 49
Height = 13
Caption = 'UserName'
end
object Label2: TLabel
Left = 16
Top = 48
Width = 35
Height = 13
Caption = 'Domain'
end
object Label3: TLabel
Left = 12
Top = 76
Width = 46
Height = 13
Caption = 'Password'
end
object Label4: TLabel
Left = 16
Top = 104
Width = 16
Height = 13
Caption = 'File'
end
object UserNameEdit: TEdit
Left = 80
Top = 16
Width = 121
Height = 21
TabOrder = 0
Text = 'UserNameEdit'
end
object DomainEdit: TEdit
Left = 80
Top = 44
Width = 121
Height = 21
TabOrder = 1
Text = 'DomainEdit'
end
object PasswordEdit: TEdit
Left = 80
Top = 72
Width = 121
Height = 21
TabOrder = 2
Text = 'PasswordEdit'
end
object ImpersonateButton: TButton
Left = 232
Top = 14
Width = 75
Height = 25
Caption = 'Impersonate'
TabOrder = 3
OnClick = ImpersonateButtonClick
end
object FileNameEdit: TEdit
Left = 80
Top = 99
Width = 121
Height = 21
TabOrder = 4
Text = 'FileNameEdit'
end
object RevertToSelfButton: TButton
Left = 232
Top = 45
Width = 75
Height = 25
Caption = 'Revert to self'
TabOrder = 5
OnClick = RevertToSelfButtonClick
end
object FileAccessButton: TButton
Left = 232
Top = 76
Width = 75
Height = 25
Caption = 'File access'
TabOrder = 6
OnClick = FileAccessButtonClick
end
end