javascript - 如何在 RESTful 中使用 VisualCaptcha 与 AngularJS 和 slimPHP

标签 javascript php angularjs captcha slim

所以我使用AngularJS在前端和 SlimPHP在带有 REST url 的后端。我正在尝试使用 VisualCaptch我按照 PHP 方面的说明进行操作,它似乎在后端工作,我制作了一个简单的 Angular dataService 调用 url 并将其显示在控制台上,但我根本不明白如何将它与 Angular 连接,我也下载了那部分但是当我创建 HTML并调用 captcha<div>里面.好吧,实际上让我解释一下问题 1,它是 Angular 试图运行的 url 是不正确的,但我只是不知道如何配置它,是否有一个选项?那么让我展示一下我到目前为止的代码...顺便说一句,我使用了 Controller as vm语法,所以你不会找到 $scope在我的代码中。

HTML:

<div captcha options="vm.captchaOptions"></div>

AngularJS Controller 代码:

// this work as a dataService call to SlimPHP
dataService.getCaptchaHowMany().then(function(data) {
    console.debug(data);
});

// where does my dataService call goes in here???
vm.captchaOptions = {
    imgPath: 'vendors/visual-captcha/img/',
    captcha: { numberOfImages: 5 },
    init: function ( captcha ) {
        vm.captcha = captcha;
    }
};

SlimPHP 路由,我知道它们有效

# Captcha Routes
$app->get('/captcha/start/:howMany', function($howMany) use ($app) { CaptchaController::getCaptchaHowMany($app, $howMany); });
$app->get('/captcha/audio(/:type)', function($type = 'mp3') use ($app) { CaptchaController::getCatpchaDiskAudioStreaming($app, $type); });
$app->get('/captcha/image/:index', function($index) use ($app) { CaptchaController::getCatpchaDiskImageStreaming($app, $index); });
$app->post('/captcha/try', function() use ($app) { CaptchaController::postCatchaTryValidate($app); }); 

当我用 Angular 复制 VisualCaptcha 的示例并运行代码时,它显示了错误的 url 调用(错误是因为我的 SlimPHP Api 位于不同的位置)。所以错误的 url 调用看起来像这样:
GET http://localhost/myproject/user/start/5

但是要正确调用我的 SlimPHP api路由应该是这样的
GET http://localhost/myproject/api/captcha/start/5

那么我应该在哪里配置 Angular 的 VisualCaptcha 路由呢???我还附上了正确 url 的结果,所以我认为我的后端 (SlimPHP) 正常工作,只是在错误的 Controller 中配置 Angular url。 enter image description here

编辑
我现在更进一步了,我发现我们可以设置urlcaptchaOptions里面现在可以正确调用我的 SlimPHP具有以下内容的 api url

vm.captchaOptions = {
    imgPath: 'vendors/visual-captcha/img/',
    captcha: { 
        numberOfImages: 5,
        url: 'api/captcha'
    },
    // use init callback to get captcha object
    init: function ( captcha ) {
        vm.captcha = captcha;
    }
};

我现在遇到的问题是它不显示图像。这些图像应该来自 PHP 还是来自客户端的 Angular?哪个文件夹应包含所有图像?我实际上在控制台中收到此错误消息:

HTTP "Content-Type" of "text/html" is not supported. Load of media resource http://localhost/investing/api/captcha/audio?r=353oeaysbjg failed.

我实际上不想要音频,虽然它给我这个音频错误,我只是想使用图像,仅此而已。请有人帮帮我!

最佳答案

经过 2 天的时间,我终于让它工作了。我必须做一些代码更改。所以这里是修改列表:

首先,我在我的 SlimPHP 应用程序中缺少 session 变量:

// Inject Session closure into app
$app->session = function() use( $app ) {
    if ( $namespace = $app->request->params( 'namespace' ) ) {
        $session = new \visualCaptcha\Session( 'visualcaptcha_' . $namespace );
    } else {
        $session = new \visualCaptcha\Session();
    }
    return $session;
};

然后更改 HTML 代码以使用 Bootstrap 而不是 Foundation,还添加了 2 个按钮来检查它是否已填充以及是否有效:

<div class="form-group">
    <label class="control-label col-sm-5">Visual Captcha Messages</label>
    <div class="col-sm-7" id="status-message">
        <div class="alert" ng-class="{ 'alert-danger': (vm.valid === false), 'alert-success': (vm.valid === true) }" role="alert" ng-show="vm.status !== null">
            <div ng-class="{ 'glyphicon glyphicon-remove-sign': (vm.valid === false), 'glyphicon glyphicon-ok-sign': (vm.valid === true) }" ></div>
            {{ vm.status }}
        </div>
    </div>
</div>

<div class="form-group">
    <label class="control-label col-sm-5">Visual Captcha</label>                
    <div class="col-sm-7" captcha options="vm.captchaOptions"></div>
</div>

<button type="button" class="btn" ng-click="vm.isVisualCaptchaFilled()">Check if visualCaptcha is filled</button>
<button type="button" class="btn" ng-click="vm.isVisualCaptchaValid()">Validate Catpcha</button>

然后在我的 AngularJS Controller 中使用 Controller as vm 语法:

vm = this;  
vm.captcha = {};
vm.captchaOptions = {
    imgPath: 'vendors/visual-captcha/img/', // vendors folder on Angular side, only used for "refresh" and "audio" buttons
    captcha: { 
        numberOfImages: 5,
        url: 'api/captcha'                  // url for SlimPHP route calls
    },
    // use init callback to get captcha object
    init: function ( captcha ) {
        vm.captcha = captcha;
    }
};

// vm public functions revealing
vm.isVisualCaptchaFilled = isVisualCaptchaFilled;
vm.isVisualCaptchaValid = isVisualCaptchaValid;

function isVisualCaptchaFilled() {
    if ( vm.captcha.getCaptchaData().valid ) {
        window.alert( 'visualCaptcha is filled!' );
    } else {
        window.alert( 'visualCaptcha is NOT filled!' );
    }
}

function isVisualCaptchaValid() {
    // we will post the captcha image field name and image field value
    var postData = {
        fieldName: vm.captcha.getCaptchaData().name,
        fieldValue: vm.captcha.getCaptchaData().value
    };

    dataService.isVisualCaptchaValid(postData)
        .then(function(data) {
            // Show success/error messages
            if ( data.status === 'noCaptcha' ) {
                vm.valid = false;
                vm.status = 'visualCaptcha was not started!';
            } else if ( data.status === 'validImage' ) {
                vm.valid = true;
                vm.status = 'Image was valid!';
            } else if ( data.status === 'failedImage' ) {
                vm.valid = false;
                vm.status = 'Image was NOT valid!';
            } else if ( data.status === 'validAudio' ) {
                vm.valid = true;
                vm.status = 'Accessibility answer was valid!';
            } else if ( data.status === 'failedAudio' ) {
                vm.valid = false;
                vm.status = 'Accessibility answer was NOT valid!';
            } else if ( data.status === 'failedPost' ) {
                vm.valid = false;
                vm.status = 'No visualCaptcha answer was given!';
            }
        })
        .then(function() {
            vm.captcha.refresh();
        });        
}

然后还必须重写 SlimPHP 应用程序中的 try 路由:

// Try to validate the captcha
// -----------------------------------------------------------------------------
$app->post( '/try', function() use( $app ) {
    $captcha = new \visualCaptcha\Captcha( $app->session );
    $frontendData = $captcha->getFrontendData();
    $isCaptchaValid = false;
    $namespace = '';
    $status = '';

    //POST variables, they come as a JSON encoded inside the POST
    $jsonPostFields = $app->request();
    $post = json_decode($jsonPostFields->getBody(), $associativeArray = true);

    // Load the namespace into url params, if set
    if ( isset($post['namespace']) ) {
        $namespace = $post['namespace'];
    }
    if ( ! $frontendData ) {
        $status = 'noCaptcha';
    } else {
        // If an image field name was submitted, try to validate it
        if(isset($post["fieldName"]) && $post["fieldName"] === $frontendData['imageFieldName']) {
            $imageAnswer = $post["fieldValue"];
            if ( $captcha->validateImage( $imageAnswer ) ) {
                $isCaptchaValid = true;
                $status = 'validImage';
            } else {
                $status = 'failedImage';
            }
        } else if(isset($post["fieldName"]) && $post["fieldName"] === $frontendData['audioFieldName']) {
            $audioAnswer = $post["fieldValue"];
            if ( $captcha->validateAudio( $audioAnswer ) ) {
                $isCaptchaValid = true;
                $status = 'validAudio';
            } else {
                $status = 'failedAudio';
            }
        } else {
            $status = 'failedPost';
        }
        $howMany = count( $captcha->getImageOptions() );
        $captcha->generate( $howMany );
    }
    echo json_encode(array("isCaptchaValid" => $isCaptchaValid, "status" => $status));
} );

请注意,使用 dataService 仅用于测试和开发目的,您应该在保存表单之前在后端验证 VisualCaptcha后端。所以理论上,你只会在 Angular 中进行 1 次调用,这是通过 dataService 进行的表单保存调用,然后在服务器后端需要发生两件事(1-验证码验证, 2-保存表格)
我还将数据修改为 post 因为我不喜欢他们完成示例的方式,我从不直接在 AngularJS SPA 应用程序中发布表单,我更喜欢使用dataServiceng-click 调用,这就是我必须定义自己的 postData 变量的原因。

经过所有这些更改...它终于可以同时处理图像和音频了!!!

关于javascript - 如何在 RESTful 中使用 VisualCaptcha 与 AngularJS 和 slimPHP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27895701/

相关文章:

javascript - 为什么在评估对象时添加括号?

cakephp 模型 virtualFields 无法通过包含工作

php - 创建 Laravel 存储库并绑定(bind)为服务提供者

javascript - 在 div 内向上滚动时无限滚动

javascript - 为什么 Await 不阻塞下一行代码?

javascript - 如何将变量从 webview Javascsript 传递到 Xamarin Forms 代码?

php - 子域路由覆盖并运行 web.php 中的最后一个子域

javascript - AngularJS:将对象存储在 cookie 中,给出 [Object Object] 的结果

javascript - IIS 8.5 中托管的 AngularJS html5Mode 路由问题

javascript - 在 JavaScript 中使用 forEach 将数组的所有元素乘以数字