Kbmmw. Time out message "Anonymous user not authorized" - delphi

I made a new topic about my issue.
KIM told\
Anonymous requests typically means that it does not find a
username/password not a token in the clients request. Remember the
Token you get on your first request should be reused for all
subsequent requests by all client code (all kbmMWSimpleClient,
kbmMWClientQuery, kbmMWClientResolver etc). On way to centralize that
is to put a TkbmMWSimpleClient on the datamodule and specify all the
client query components to use this simple client instance as a
template. Then as the first thing before anything else in your client
application, make an initial "login" request call via the
simpleclient.
I changed ServerSideQueryAllClick on the client app. I copied Token from server side to client Edit1.text.
procedure TForm1.btnNamedServerSideQueryAllClick(Sender: TObject);
begin
// Gets all records from server event table.
If Length(Trim(Edit1.Text)) > 0 then
Begin
kbmMWSimpleClient1.Disconnect;
kbmMWSimpleClient1.Username:= CB1.Text; // Login -> Franz
kbmMWSimpleClient1.Password:= CB2.Text; // Password -> FranzPassword
kbmMWSimpleClient1.Token := Edit1.Text; // Token from server
kbmMWSimpleClient1.Connect;
End;
if qServerSide.Active then qServerSide.Close;
// Use named query.
qServerSide.Query.Text:='#ALL_EVENTS';
qServerSide.Open;
end;
It dowsn't work.
How to make relogin?

The Authorization demo shows how the client has a simpleclient that is used as template for all the client query components (by setting their Client property to point at the simpleclient instance).
When setting the token, you specifically do not want to set the username or password, and similarly if you are setting username and password, do not set the token.
Also make sure that qServerSide.Client points on your simpleclient.
Doing that you generally only need to setup username/password once on the simpleclient before anything is opened, then for example open the query component, after which the simpleclient.token value will automatically have been updated from the server with the assigned login token.

Related

Delphi XE2 DataSnap Server - Log client connection user/properties

I'm building an XE2 DataSnap server which will serve connections from REST clients. My DSServerClass LifeCycle property is set to 'Invocation'. What I want to do is to log the details of all client connections to the server, including the following details : username, IP address, protocol, application name. I can currently get these details using the following events :
DSAuthenticationManager - UserAuthenticate() : username, protocol (using the standard parameters passed in)
DSServer - Connect() : protocol, IP address, application name (using DSConnectEventObject.ChannelInfo.ClientInfo)
What I want to do is just log once for all details, but it seems I can't get all the details I need in one event. I tried using a shared private variable in the class but as expected this gave inconsistent results - the wrong IP address against the wrong username. Is there another way to achieve what I want?
Jonathan
procedure TServerContainer1.DSServer1Connect(DSConnectEventObject: TDSConnectEventObject);
begin
Form1.Memo1.Lines.Add(Format('Conn->UserName=%s, Password=%s', [
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName],
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password]
]));
// 取 Client 端的IP 和 Port
Form1.Memo1.Lines.Add('IP =' + DSConnectEventObject.ChannelInfo.ClientInfo.IpAddress + ':'
+ DSConnectEventObject.ChannelInfo.ClientInfo.ClientPort);
end;
You can use TDSServer.OnConnect event (which is called after TDSAuthenticationManager.OnUserAuthenticate). There you have access to ChannelInfo.ClientInfo as you've discovered and also ConnectProperties from which you can read property values like this:
Scheme := ConnectProperties.Values[TDBXPropertyNames.DSAuthenticationScheme];
UserName := ConnectProperties.Values[TDBXPropertyNames.DSAuthenticationUser];
Password := ConnectProperties.Values[TDBXPropertyNames.DSAuthenticationPassword];

username is null in DotNetOpenAuth2.ResourceServer.VerifyAccess

I have implemented an authorization server based on the sample and am receiving an access token in response to client credentials request. From my understanding this access token has a null username because it is not tied to a user.
I have implemented a resource server also based on the sample. When I try to validate the access token in my wcf server (resource server) in OAuthAuthorizationManager.VerifyOAuth2 I get an ArgumentNullException for username from
var error = resourceServer.VerifyAccess(httpRequestInfo, out result);
How can I modify OAuthAuthorizationManager to allow a null username?
Do I create a generic principal on the fly and assign it to the scope in the token.
i.e. should I use
var error = resourceServer.VerifyAccess(httpRequestInfo, out userName, out scope);
instead?
This is an issue with DotNetOpenAuth v4.0. v4.1 has this issue fixed. It's not released yet, but you can snag a copy from NuGet if you point it at this channel:
http://teamcity.dotnetopenauth.net:82/guestAuth/app/nuget/v1/FeedService.svc

Delphi XE2 DataSnap - Access REST connection properties in server methods module

I'm building an XE2 DataSnap server which will serve connections from REST clients. My DSServerClass LifeCycle property is set to 'Invocation'. The REST connection properties will include username and password, which are handled through the DSAuthenticationManager UserAuthenticate() event. What I need to know is how can I access the username and password within the server methods class? I want to be able to know which REST username/password launched the object instance of my server class.
You can use DSServerClass.OnPrepare for that:
procedure TServerContainerTest.DSServerClass1Prepare(
DSPrepareEventObject: TDSPrepareEventObject);
begin
// Add username property to TServerMethodsTest
if DSPrepareEventObject.MethodInstance is TServerMethodsTest then
TServerMethodsTest(DSPrepareEventObject.MethodInstance).Username := DSPrepareEventObject.UserName;
end;
There's is no password available.
Don't use Server LifeCycle for this!

Send an email with attachment Client Agnostic

I currently have an application written that generates pdf vouchers and emails to their perspective recipients. However the function I use is client dependent (MS Outlook) and I would really like to make this email client agnostic as we have many customers and not all of them use Outlook.
I have looked at a few options but can't really find anything in searching that seems to solve my problem.
Does anyone know a good way to send email using the customers smtp connection regardless of the client and send an attachment with it without calling the client directly to do it?
Or you can use the Synapse library, for sending a mail using SMTP, ideally in its newest snapshot.
Here is the code which should send the mail with attached c:\voucher.pdf file from sender#from.com to recipient#to.com to the smtp.server.com with login login and password password. About the rest of the functions from the TMimeMess class I would refer you directly to the reference.
I hope this will work because I've simplified and localized much more complicated code I'm using and I can't verify it nor compile. If not, let's downvote it :)
uses
SMTPSend, MIMEPart, MIMEMess;
procedure TForm.SendEmailClick(Sender: TObject);
var
MIMEText: TStrings;
MIMEPart: TMimePart;
MIMEMessage: TMimeMess;
begin
MIMEText := TStringList.Create;
MIMEText.Add('Hello,');
MIMEText.Add('here is the text of your e-mail message,');
MIMEText.Add('if you want the HTML format, use AddPartHTML');
MIMEText.Add('or e.g. AddPartHTMLFromFile if you have your');
MIMEText.Add('HTML message content in a file.');
MIMEMessage := TMimeMess.Create;
with MIMEMessage do
try
Header.Date := Now;
Header.From := 'sender#from.com';
Header.ToList.Clear;
Header.ToList.Add('recipient#to.com');
Header.CcList.Clear;
Header.Subject := 'E-mail subject';
Header.XMailer := 'My mail client name';
MIMEPart := AddPartMultipart('mixed', nil);
AddPartText(MIMEText, MIMEPart);
AddPartBinaryFromFile('c:\voucher.pdf', MIMEPart);
EncodeMessage;
if SendToRaw(Header.From, // e-mail sender
Header.ToList.CommaText, // comma delimited recipient list
'smtp.server.com', // SMTP server
Lines, // MIME message data
'login', // server authentication
'password') // server authentication
then
ShowMessage('E-mail has been successfuly sent :)')
else
ShowMessage('E-mail sending failed :(');
finally
Free;
MIMEText.Free;
end;
end;
Update:
According to nice comment from Downvoter step into the light (man, change your nick please, it's not cool anymore :), would be really bad if you will send the list of all recipients to everyone. With synapse you cannot add BCCs to the message header; there's no Header.BCCList property in MIMEMessage.
Instead you can directly modify the data before sending them.
// First, you will remove the line where you are adding a recipient to the list
Header.ToList.Add('recipient#to.com');
// the rest between you can keep as it is and after the message encoding
EncodeMessage;
// and before sending the mail you'll insert the line with BCCs
Lines.Insert(1, 'Bcc: jane#invisiblecustomer.com, lisa#invisiblecustomer.com');
if SendToRaw ...
You could use Indy as your SMTP client, independent of the system default e-mail client. Here's a basic demo of sending e-mails without attachments, and there are detailed articles here and here about sending HTML or plain-text e-mails and with or without attachments.
If you want to integrate with the existent email client (e.g. see the sent messages in the sent, sent items, etc. folder of the email client), you could use Simple MAPI. The headers are translated in the Mapi unit in Delphi (at least in D2007).
But be careful to check if the actual client supports Simple MAPI.

How can my program log in to a Web site programmatically with Indy?

I am trying to log in to fileserve.com from my Delphi application.
I used the LiveHTTPHeader Firefox addon to see HTTP post data. I found
&autoLogin=on&recaptcha_response_field=&recaptcha_challenge_field=&recaptcha_shortencode_field=&loginFormSubmit=Login
I tried in my application like this:
Str := TStringList.Create;
Str.Add('loginUserName='+edit1.Text);
Str.Add('loginUserPassword='+edit2.Text);
Str.Add('autoLogin=on');
Str.Add('recaptcha_response_field=');
Str.Add('recaptcha_challenge_field=');
Str.Add('recaptcha_shortencode_field=');
Str.Add('loginFormSubmit=Login');
s:= IdHTTP1.Post('http://www.fileserve.com/login.php', Str);
FreeAndNil(str);
s1 := IdHTTP1.Get('http://www.fileserve.com/dashboard.php');
memo1.lines.add(s1);
In my my memo, it's not giving the data after I logged in. It just displays the source of the main site. Why doesn't it recognize that I logged in? (I used a working ID and password while testing.)
I am using Delphi 7 and Indy 9; The IdHTTP.HandleRedirect property is set to true.
The site you're logging in to probably sends a cookie in its response to the login request. You need to remember that cookie and send it back during all subsequent requests. Indy should have some sort of TIdCookieManager object that you can hook up to your TIdHTTP object to make it remember cookies automatically.

Resources