【问题标题】:How to use VisualCaptcha with AngularJS and slimPHP in RESTful如何在 RESTful 中将 VisualCaptcha 与 AngularJS 和 slimPHP 一起使用
【发布时间】:2015-01-12 05:14:07
【问题描述】:

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

HTML:

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

AngularJS 控制器代码:

// 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

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

编辑
我现在走得更远了,我发现我们可以在 captchaOptions 内设置 url,现在可以正确调用我的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.

我实际上不想要音频,虽然它给了我这个音频错误,我只是想使用图像,仅此而已。谁能帮帮我,拜托!

【问题讨论】:

    标签: javascript php angularjs captcha slim


    【解决方案1】:

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

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

    // 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 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 进行的表单保存调用,然后在服务器后端需要发生 2 件事(1-验证码验证,2-保存表单)
    我还将数据修改为post,因为我不喜欢他们的示例方式,我从不直接在 AngularJS SPA 应用程序中发布表单,我更喜欢使用由ng-click 这就是为什么我必须定义自己的 postData 变量。

    随着所有这些变化......它最终适用于图像和音频!!!

    【讨论】:

      猜你喜欢
      • 2014-02-05
      • 2014-08-05
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-20
      相关资源
      最近更新 更多