【问题标题】:RESTfull way to check if a user can connect with Slim检查用户是否可以连接 Slim 的 RESTful 方式
【发布时间】:2016-01-28 00:44:01
【问题描述】:

我有一个 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() 进行比较。我知道如果它有效,我想返回 2 个特定字段,但如果我仍然希望我的 API 被视为 RESTfull,我不确定该怎么做。

【问题讨论】:

    标签: angularjs connection slim restful-architecture


    【解决方案1】:

    在涉及 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 的 Authorization 标头:

    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 应该作为 Authorization 标头发送到每个后续请求,直到浏览器窗口关闭或手动重置 $window.sessionStorage.token

    希望这会有所帮助:)

    【讨论】:

    • 我不确定我是否理解。我想在哪里检查用户是否提供了正确的用户名/密码?密码验证()在哪里?
    • 我的问题是我应该把代码放在哪里来检查用户是否可以连接?我是否应该使用(GET、POST 或 PUT)api/身份验证调用身份验证功能?该函数是否应该获取给定用户名的密码,然后将其与给定密码进行比较以查看它是否合适,然后返回一些信息或一条消息,表明它不起作用?所有这些都应该在我的 API 函数中完成还是违背了 RESTful?我应该使用 GET、POST 还是 PUT?
    • 我有几个问题; 1---什么是 $key = "example_key"; 2---有了这个,我不需要在我的数据库中有会话密钥之类的东西吗? 3--- 我可以将用户名和权限存储在 cookie 中吗?这样安全吗? 4--- 如果有人试图更改令牌的内容,它会注意到它使令牌无效吗?
    猜你喜欢
    • 2020-04-19
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多