检查用户是否可以连接 Slim 的 RESTful 方式

RESTfull way to check if a user can connect with Slim

我有一个 SLim API,我在我的 ANgularJS 应用程序中使用它来访问我的数据库(例如):

我的控制器:

$scope.testDatabaseItems = function(){
    $http.get(pathApi + 'items').success(function(data) {
        $log.info("succes!");
        $log.log(data);
        $scope.items=data;
    })
    .error(function (data, status){
        $log.error("error!");
        $log.log(data);
    });
};

我的 Slim 应用程序:

<?php

require 'vendor/autoload.php';
require 'config/config.php';

$app = new \Slim\App;

$app->get('/items', 'getItems');
$app->get('/items/{id:\d+}', 'getItemById');
$app->post('/new_user', 'addUser');
$app->get('/users', 'getUsers');

$app->run();

function DB_Connection() {
    global $dbparams;
    $dbhost = $dbparams['host'];
    $dbuser = $dbparams['user'];
    $dbpass = $dbparams['password'];
    $dbname = $dbparams['dbname'];
    $dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);  
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    return $dbh;
}

function getItems() {
    $sql = "SELECT * FROM aj_items";
    try {
        $db = DB_Connection();
        $stmt = $db->query($sql);  
        $list = $stmt->fetchAll(PDO::FETCH_OBJ);
        $db = null;
        echo json_encode($list);
    } catch(PDOException $e) {
        echo '{"error":{"text":'. $e->getMessage() .'}}'; 
    }
}

?>

我的问题是我想调用我的 Slim 应用程序来检查用户名和密码是否有效(连接),但我想要一个 RESTfull API 并且我在 RESTfull API,我通常使用其中之一:GET、POST、DELETE 或 PUT。

我不知道我可以使用哪个,因为我只是查看一些信息并将其与 password_verify() 进行比较。我知道我想要 return 2 个特定字段(如果它有效),但是如果我仍然希望我的 API 被视为 RESTfull,我不确定该怎么做。

在涉及 Restful API 的应用程序环境中,建议使用 JSON Web Tokens (JWT) 在各方之间传递声明。

在您的 Slim 应用程序中使用 firebase/php-jwt

composer require firebase/php-jwt

然后在你的路线中

<?php

require 'vendor/autoload.php';

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

$app = new \Slim\App;

$app->get('/authenticate', function (Request $request, Response $response) {
    $key = "example_key";
    $token = array(
        "iss" => "http://example.org",
        "aud" => "http://example.com",
        "iat" => 1356999524,
        "nbf" => 1357000000
    );
    $jwt = JWT::encode($token, $key);
    $response->getBody->write(json_encode(['token' => $jwt]));
    return $response;
});


$app->get('/items', function (Request $request, Response $response){
    $key = "example_key";
    $token = $request->getHeader('HTTP_AUTHORIZATION');
    if (!empty($token) && is_array($token)) {
        $token = trim(str_replace('Bearer', '', $token[0]));
        if (JWT::decode($token, $key, ['HS256'])) {
            // User authentication successful
        } else {
            // User authentication failed
        }
    }
});
?>

现在您需要将 /authenticate 返回的 JWT 缓存在某处。使用 window.sessionStorage 是个好主意,因为数据会一直存在,直到浏览器选项卡关闭,more on cookies vs tokens

$scope.testDatabaseItems = function(){
  $http.get(pathApi + 'authenticate')
    .then(function (response){
        if (response.data.token !== undefined && response.data.token.length) {
            $window.sessionStorage.token = response.data.token;
        }
    }, function (reason){
        console.log(reason);
    }
  );
};

此时您需要告诉 Angular 捕获每个请求,在使用拦截器将其发送到服务器之前添加包含 JWT 的授权 header:

var app = angular.module('myApp', []);

app.config(['$httpProvider', function($httpProvider){
  $httpProvider.interceptors.push('AuthInterceptor');
}]);

app.factory('AuthInterceptor', ['$q', '$window', function ($q, $window) {
  return {
    request: function (config) {
      config.headers = config.headers || {};
      if ($window.sessionStorage.token) {
        config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
      }
      return config;
    },
    response: function (response) {
      return response || $q.when(response);
    }
  };
}]);

无需进一步配置。在您的应用程序调用 /items 之前,它首先需要调用 /authenticate 之后,JWT 应该作为授权 header 在每个后续请求中发送,直到浏览器 window关闭或 $window.sessionStorage.token 手动重置。

希望这对您有所帮助:)