|
| 1 | +#!/usr/bin/env perl |
| 2 | + |
| 3 | +# reCAPTCHA is a CAPTCHA system, that is a system that allows web hosts to distinguish between human |
| 4 | +# and automated access to websites. More info - https://www.google.com/recaptcha/about/ |
| 5 | +# You can register your site in google reCAPTCHA at https://www.google.com/recaptcha/admin/create |
| 6 | +# You will get 'Site Key' and 'Secret Key'. |
| 7 | +# 'Site Key' will be put on front-end side while 'Secret key' will be on server side in environemnt variable. |
| 8 | + |
| 9 | +# https://metacpan.org/pod/Mojolicious |
| 10 | +# https://docs.mojolicious.org/Mojolicious/Lite |
| 11 | + |
| 12 | +# This is a simple Login page. We will be authenticating user. |
| 13 | +# After success they will get a home page where we will be welcoming them and they can logout from there. |
| 14 | +# In case of authentication failure error will be thrown. |
| 15 | + |
| 16 | +use strict; |
| 17 | +use warnings; |
| 18 | +use Mojolicious::Lite; |
| 19 | +use Mojo::UserAgent; |
| 20 | + |
| 21 | +# Add your 'Secret Key' here |
| 22 | +$ENV{'CAPTCHA_V2_SECRET_KEY'} = ""; |
| 23 | + |
| 24 | +sub is_valid_captcha { |
| 25 | + my ($c) = @_; |
| 26 | + my $ua = Mojo::UserAgent->new; |
| 27 | + $ua->insecure(1); |
| 28 | + my $param = $c->param('g-recaptcha-response'); |
| 29 | + |
| 30 | + my $captcha_url = 'https://www.google.com/recaptcha/api/siteverify'; |
| 31 | + my $response |
| 32 | + = $ua->post( |
| 33 | + $captcha_url => form => {response => $param, secret => $ENV{'CAPTCHA_V2_SECRET_KEY'}}) |
| 34 | + ->result; |
| 35 | + if ($response->is_success()) { |
| 36 | + my $out = $response->json; |
| 37 | + if ($out->{success}) { |
| 38 | + return 1; |
| 39 | + } |
| 40 | + else { |
| 41 | + return 0; |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + # Connection to reCAPTCHA failed |
| 46 | + return 0; |
| 47 | +} |
| 48 | + |
| 49 | +# https://docs.mojolicious.org/Mojolicious/Lite#Helpers |
| 50 | +# Check for authentication |
| 51 | +helper auth => sub { |
| 52 | + my $c = shift; |
| 53 | + |
| 54 | + if (($c->param('username') eq 'admin') && ($c->param('password') eq 'admin')) { |
| 55 | + return 1; |
| 56 | + } |
| 57 | + return 0; |
| 58 | +}; |
| 59 | + |
| 60 | +helper verify_captcha => sub { |
| 61 | + my $c = shift; |
| 62 | + if (is_valid_captcha($c)) { |
| 63 | + return 1; |
| 64 | + } |
| 65 | + return 0; |
| 66 | +}; |
| 67 | + |
| 68 | +# Different Routes |
| 69 | +get '/' => sub { shift->render } => 'index'; |
| 70 | + |
| 71 | +post '/login' => sub { |
| 72 | + my $c = shift; |
| 73 | + if ($c->auth) { |
| 74 | + if ($c->verify_captcha) { |
| 75 | + $c->session(auth => 1); |
| 76 | + $c->flash(username => $c->param('username')); |
| 77 | + return $c->redirect_to('home'); |
| 78 | + } |
| 79 | + else { |
| 80 | + $c->flash('error' => 'Captcha verification failed'); |
| 81 | + $c->redirect_to('index'); |
| 82 | + } |
| 83 | + } |
| 84 | + $c->flash('error' => 'Wrong login/password'); |
| 85 | + $c->redirect_to('index'); |
| 86 | +} => 'login'; |
| 87 | + |
| 88 | +get '/logout' => sub { |
| 89 | + my $c = shift; |
| 90 | + delete $c->session->{auth}; |
| 91 | + $c->redirect_to('index'); |
| 92 | +} => 'logout'; |
| 93 | + |
| 94 | +# https://docs.mojolicious.org/Mojolicious/Lite#Under |
| 95 | +under sub { |
| 96 | + my $c = shift; |
| 97 | + return 1 if ($c->session('auth') // '') eq '1'; |
| 98 | + |
| 99 | + $c->render('denied'); |
| 100 | +}; |
| 101 | + |
| 102 | +get '/home' => sub { |
| 103 | + my $c = shift; |
| 104 | + $c->render(); |
| 105 | +} => 'home'; |
| 106 | + |
| 107 | +app->start; |
| 108 | + |
| 109 | +__DATA__ |
| 110 | + |
| 111 | + |
| 112 | +@@ index.html.ep |
| 113 | +<html> |
| 114 | + <head> |
| 115 | + <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet"> |
| 116 | + <script src="https://www.google.com/recaptcha/api.js" async defer></script> |
| 117 | + </head> |
| 118 | + <body> |
| 119 | + %= t h1 => 'Login' |
| 120 | + |
| 121 | + % if (flash('error')) { |
| 122 | + <h2 style="color:red"><%= flash('error') %></h2> |
| 123 | + % } |
| 124 | + |
| 125 | + %= form_for login => (method => 'post') => begin |
| 126 | + <label>username:</label> <%= text_field 'username' %> |
| 127 | + <br /><br /> |
| 128 | + <label>password:</label> <%= password_field 'password' %> |
| 129 | + <br /><br /> |
| 130 | + <div class="g-recaptcha" data-sitekey="<Your Site-key>"></div> |
| 131 | + %= submit_button 'Log in' |
| 132 | + %= end |
| 133 | + </body> |
| 134 | +</html> |
| 135 | + |
| 136 | + |
| 137 | +@@ home.html.ep |
| 138 | +%= t h1 => 'Home Page' |
| 139 | +<h2 style="color:green">Hello <%= flash('username') %></h2> |
| 140 | +<a href="<%= url_for('logout') %>">Logout</a> |
| 141 | + |
| 142 | + |
| 143 | +@@ denied.html.ep |
| 144 | +%= t h2 => 'Access Denied' |
| 145 | +<a href="<%= url_for('index') %>">Login</a> |
| 146 | + |
0 commit comments