Acme-CPANModulesBundle-Import-MojoliciousAdvent-2018
view release on metacpan or search on metacpan
devdata/https_mojolicious.io_blog_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
$sth->execute($username, $password) or return;
my @row = $sth->fetchrow_array();
$sth->finish();
return $username eq $row[0];
}
</code></pre>
<p>with the database connection and handle <code>$dbh</code> left as an exercise to the reader.
And yes, you should prepare the SQL outside of the sub.
The <code>?</code> in the SQL statement are bind parameters, placeholders that make the database call faster and safer.</p>
<h4>Did you spot the HUGE mistake I made?</h4>
<p>Never, never, NEVER store passwords in plain text! (Blame it on Friday afternoon)
You should encrypt the password before storing it with an algorithm like AES or SHA-2.
So, how about this for a better untested example? You can encrypt with SQL</p>
<pre><code> my $statement = <<'SQL'; # better
SELECT username FROM user_passwd
WHERE username = ? AND password = SHA2(?, 256)
devdata/https_mojolicious.io_blog_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
<ol>
<li>Connect to the LDAP server</li>
<li><strong>Bind</strong> to the server</li>
<li>Search for the user's unique identifier in LDAP</li>
<li><strong>Bind</strong> as the user with their password</li>
<li>Check the result code from the server</li>
</ol>
<p>First, you need to make a network connection to the LDAP server.
Next, you <a href="https://metacpan.org/pod/Net::LDAP#METHODS">bind</a> to the server.
"Bind" is the term used in LDAP for connecting to a particular location
in the LDAP tree.
The LDAP server has a setting on whether it allows binding anonymously
and determines whether you can search directory without a password
as I've done in the example.
Then you search LDAP for the user (because the identifiers are <em>loooong</em>)
and then you bind as the user with the password they've provided.
If this connection as the user with their password succeeds,
then you must have used the correct password.
LDAP hands you back a result from the <code>bind</code> as a
<a href="https://metacpan.org/pod/distribution/perl-ldap/lib/Net/LDAP/Message.pod">Net::LDAP::Message</a>
object on either success or failure,
so check the Message <code>code</code> to find out whether you should authenticate the user.</p>
<p>Here's the code</p>
<pre><code>package MyApp::Controller::Secure;
use Mojo::Base 'Mojolicious::Controller';
use Net::LDAP qw/LDAP_INVALID_CREDENTIALS/;
use YAML qw/LoadFile/;
devdata/https_mojolicious.io_blog_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
= @{$config}{ qw/server baseDN username id/ };
...
sub check_credentials {
my ($username, $password) = @_;
return unless $username;
my $ldap = Net::LDAP->new( $LDAP_server )
or warn("Couldn't connect to LDAP server $LDAP_server: $@"), return;
my $message = $ldap->bind( $base_DN );
my $search = $ldap->search( base => $base_DN,
filter => join('=', $user_attr, $username),
attrs => [$user_id],
);
my $user_id = $search->pop_entry();
return unless $user_id; # does this user exist in LDAP?
# this is where we check the password
my $login = $ldap->bind( $user_id, password => $password );
# return 1 on success, 0 on failure with the ternary operator
return $login->code == LDAP_INVALID_CREDENTIALS ? 0
: 1;
}
</code></pre>
<p>where you have a file <code>ldap_config.yml</code> in the top-level directory that looks a little like</p>
<pre><code># config values for connecting to LDAP
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
<p>Components are the most basic UI building block of an Angular app. An Angular app contains a tree of Angular components.
Component basically creates a separate MVC world which makes code management granular and easy.
The <code>@Component</code> decorator can pass in many types of metadata to a class particularly following 3 metadata specifiers are significant:</p>
<ul>
<li><code>selector</code>: specifies which UI component it targets.</li>
<li><code>templateUrl</code>: html for that selector element and</li>
<li><code>styleUrl</code>: specifies one or more style files to be used for that html</li>
</ul>
<p><code>Component Class</code> sets up stage for two way data binding. In our case, it just makes an HTTP GET request to Mojo route we defined earlier, then binds the output to variable <code>adventDetail2018</code>. This is then available in the vi...
<pre><code>Sachin@12:33 AM[~/workspace/project/mojo_angular/NgDemo/src/app]$ cat app.component.ts
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
Welcome to {{ title }}!
</h1>
<h3>Mojolicious Advent Calendar 2018 Detail:</h3>
<table>
<thead>
<th>Day</th>
<th>Title</th>
<th>Author</th>
</thead>
<tbody>
<!--Angular two way data binding in action-->
<tr *ngFor="let d of adventDetail2018">
<td>{{d.day}}</td>
<td>{{d.title}}</td>
<td>{{d.author}}</td>
</tr>
</tbody>
</table>
</div>
<router-outlet></router-outlet>
</code></pre>
( run in 2.281 seconds using v1.01-cache-2.11-cpan-2398b32b56e )