2

我想知道,如何将 Codeigniter 的表单验证与 Web 服务一起使用?我正在使用 REST 和 cURL 连接 Web 服务,并尝试在登录页面上使用表单验证。当用户名或密码字段为空时,我可以让它返回错误,但我不确定如何使用它来检查密码是否匹配。我的 cUrl 代码如下:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-DocuSign-Authentication: $header"));
curl_setopt($ch, CURLOPT_UNRESTRICTED_AUTH, 1);
$output = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$this->form_validation->set_rules('username', 'USERNAME', 'required|is_unique[username]');
$this->form_validation->set_rules('password', 'PASSWORD', 'required|matches[password]');
if ($this->form_validation->run() == FALSE) {
    curl_close($ch);
    $this->load->view('error_login');
} else {        
    $response = json_decode($output, true);
    $accountId = $response["loginAccounts"][0]["accountId"];
    $baseUrl = $response["loginAccounts"][0]["baseUrl"];
    $userName = $response["loginAccounts"][0]["userName"];
    curl_close($ch);
    $username = $userName;
    $docusignURL = $baseUrl;
    $docHeader = $header;
    $loggedIn = array('is_logged_in' => true);
    $this->session->set_userdata('username', $username);
    $this->session->set_userdata('docusignURL', $docusignURL);
    $this->session->set_userdata('docHeader', $docHeader);
    $this->session->set_userdata($loggedIn);
    redirect('/create_envelope', 'refresh');
}

现在它返回两个错误通知,“未定义偏移量:1”和“未定义属性:Login::$db”。后者是因为,我假设,我没有使用模型连接到任何数据库。任何有用的建议都会非常出色。

编辑:所以我尝试了回调路由,但我收到了 500 个错误。到目前为止,这是我的整个控制器代码:

<?php
    class Login extends CI_Controller {

        function index() {
            $this->load->view('al_login');
        }

        function authenticate(){

            $post = $this->input->post();
            extract($post);

            $integratorKey = '****-********-****-****-****-************';       
            $header = "<DocuSignCredentials><Username>" . $username . "</Username><Password>" . $password . "</Password><IntegratorKey>" . $integratorKey . "</IntegratorKey></DocuSignCredentials>";
            $url = "https://demo.docusign.net/restapi/v2/login_information";

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-DocuSign-Authentication: $header"));
            curl_setopt($ch, CURLOPT_UNRESTRICTED_AUTH, 1);
            $output = curl_exec($ch);
            $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $response = json_decode($output, true);
            $accountId = $response["loginAccounts"][0]["accountId"];
            $baseUrl = $response["loginAccounts"][0]["baseUrl"];
            $userName = $response["loginAccounts"][0]["userName"];
            curl_close($ch);
            $username = $userName;
            $docusignURL = $baseUrl;
            $docHeader = $header;
            $loggedIn = array('is_logged_in' => true);
            $this->session->set_userdata('username', $username);
            $this->session->set_userdata('docusignURL', $docusignURL);
            $this->session->set_userdata('docHeader', $docHeader);
            $this->session->set_userdata($loggedIn);
            $this->form_validation->set_rules('username', 'USERNAME', 'required');
            $this->form_validation->set_rules('password', 'PASSWORD', 'required|callback_password_check');

            if ($this->form_validation->run() == FALSE) {
                $this->load->view('al_login');
            } else {
                $this->load->view('/create_envelope');
            }
        }

        function password_check($str){

            // send the user name to the service 
            if ( $this->authenticate($str) == true ) {
                return true; 
            } else { 
                // customize the message with something 
                $this->form_validation->set_message('password_check', 'The %s is incorrect. Please try again');
                return false;
            } 
        }       
    }

我是 REST、cURL 和 Codeigniter 的新手,所以我的知识可以使用帮助。到目前为止,感谢你们俩。任何想法为什么我会收到 500 个错误?

新编辑: @Petre 所以这是我们网络服务的响应:

Array ( 
    [loginAccounts] => Array ( 
        [0] => Array ( 
            [name] => ******** 
            [accountId] => ******* 
            [baseUrl] => https://demo.docusign.net/restapi/v2/accounts/******* 
            [isDefault] => true 
            [userName] => **** ******** 
            [userId] => ********-****-****-****-************ 
            [email] => ****@******.com
            [siteDescription] => 
        ) 
    ) 
)

好像不是那种东西。

4

2 回答 2

1

我在上面的代码中看到的主要问题是意大利面条因素,因为它阻碍了对重要内容的看法。你想做什么?

  1. 显示带有提交按钮的表单。
  2. 在特定 URL/操作处从表单接收数据。
  3. 验证表格。
    1. 如果数据无效,显示表格并告知用户错误。
    2. 如果数据有效,则将数据发送到 Web 服务。
      1. 如果数据无效,将用户重定向到表单并通知无效用户/密码组合。
      2. 如果数据有效,则在会话中保存一些数据以存储身份验证因素。

我们不要关注第 1 步和第 2 步,因为它们很可能已经开始工作。因此,让我们讨论表单验证。

$this->form_validation->set_rules('username', 'USERNAME', 'required|is_unique[username]');
$this->form_validation->set_rules('password', 'PASSWORD', 'required|matches[password]');

请记住,在此阶段您正在验证表单,您无权访问关系数据库(因为数据是通过 web 服务检索的,最好是在不同的服务器上),您只想确保用户名和密码字段在表格已填写。您只想确保提供了它们,也许它们具有特定的长度。让我们重温一下上面的代码。

$this->form_validation->set_rules('username', 'USERNAME', 'required|min_length[5]');
$this->form_validation->set_rules('password', 'PASSWORD', 'required|min_length[5]');

请记住,您只是在此阶段验证通过表单收到的数据 - 您不关心 web 服务端发生了什么,该端担心提供该服务。

接下来我们需要看看在表单验证失败或成功的情况下我们要做什么。我们目前的基本计划是:

if ($this->form_validation->run() == FALSE) {
    //Username or password field were not provided or they were too short.
    //Render form and display errors.
} else {
    //Username and password field have been provided and they were within the length requirements.
    //Call cURL library and call webservice.
    //Retrieve webservice response.

    if ($response == 'valid') {
        //Webservice told us that username/password combo was right!
        //Store some data in the session to authenticate user.
    } else {
        //Webservice response told us that username/password combo is not right.
        //Render login form and inform user that user/pass combo were not correct.
    }
}

我们现在只有评论 - 这是我们的计划,对吧?我们已经验证我们从用户那里得到了一些正确的输入(输入清理),现在我们想看看这些值是否正确。

但是现在,与其添加所有这些代码块,不如让我们做一些好的设计并为它使用模型!

if ($this->form_validation->run() == FALSE) {
    //Username or password field were not provided or they were too short.

    $this->load->view('myview');
} else {
    //Username and password field have been provided and they were within the length requirements.

    $username = $this->input->post('username');
    $password = $this->input->post('password');

    // Make call to webservice with parameters to check if the credentials are correct or not.
    $response = $this->muser->checkLoginCredentials($username, $password)

    if ($response->valid == 'valid') {
        //Webservice told us that username/password combo was right!

        $this->muser->storeLoginCredentials($response->fullName, $response->email, $response->username);
    } else {
        //Webservice response told us that username/password combo is not right.

        $data['error'] = 'Invalid username/password combination';
        $this->load->view('myview', $data);
    }
}

我们的代码现在超级清晰!我们只需要创建 Muser 模型并确保它有两个方法:

  • checkLoginCredentials:使用我们知道已清理的用户名和密码调用 Web 服务并检索响应。
  • storeLoginCredentials:给定来自 Web 服务响应的一些参数,将这些数据存储在会话中。

现在,为什么您的代码第一次不起作用?

  • 您在用户名上有一个 is_unique[username] 规则,但您没有与用于该数据库的数据库进行交互。您不是在检查用户名是否唯一,您只是希望网络服务告诉您您的登录凭据是否正确。
  • 您还对密码有一个 matches[password] 规则,但它什么都不做。您可能正在考虑拥有一个 _password_confirmation_ 字段,是的,该规则将适用于那里。

很抱歉写了这么长的文章,希望它能帮助并清理更多的事情。如果我可以提供更多信息,请发表评论,我会更新答案!

于 2013-10-11T21:30:09.540 回答
0

我认为您想要的被命名为“回调”,请参见此处http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#callbacks

首先确保您的 curl 休息代码工作正常。只需让它回显真假或简单的东西,以便您验证其结果。然后将其集成到您的回调中。

从手册中的示例开始,他们将其命名为:callback_username_check

 function username_check($str){

 // send the user name to the service 
 if ( $this->_sendUserName($str) == true ) 
 { return true ; } 

 else{ 
  // customize the message with something 
  $this->form_validation->set_message('username_check', 'The %s is incorrect so have another cup of coffee and try again');
  return false ; } 

 }

请注意,我正在调用一个单独的方法,该方法仅具有 rest/curl 代码。这样,如果您的服务发生变化,您就不必更改回调。

编辑 - 我只是使用“用户名”的例子来使其与指南中的例子保持一致。

如果您需要将用户名和密码都发送到服务,我的建议是对用户名进行基本验证,然后对密码进行回调。所以密码的值来自回调,然后从获取用户名的值

   $username = $this->input->post('username', TRUE);

您可以在验证之前或之后的任何地方使用 $this->input->post() 。TRUE xss 清理它。

通常,如果有人弄乱了用户名和密码,则其密码不正确。因此,通过使用回调进行验证,如果失败 - 当您再次显示表单时 - 用户名仍将被填写。并且,如果您从服务中获取有关失败原因的信息 - 您可以自定义与该信息一起显示的错误消息。

于 2013-10-11T22:13:04.580 回答