使用会话VS令牌API认证 [英] Using Sessions vs Tokens for API authentication

查看:169
本文介绍了使用会话VS令牌API认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立了一个简单的测试API的应用程序的CakePHP,将让从移动设备(或与此有关的任何设备)用户登录并获得一个JSON响应。该API可用于建在PhoneGap的移动应用。

登录方法看起来像这样:

 公共职能登录()
{
    如果($这个 - >请求 - '是('后'))
    {
        在型号//使用自定义的方法来找到密码params记录
        $ findUser = $这个 - >用户 - > findUser(
            $ _ POST ['username_or_email'],
            AuthComponent ::密码($ _ POST ['密码'])
        );        //如果用户存在并匹配PARAMS
        如果($ findUser)
        {
            $这个 - >用户 - > ID = $ findUser ['用户'] ['身份证'];            $这个 - > autoRender = FALSE;
            $这个 - >&响应 - GT;类型('JSON');
            $这个 - >响应 - >机身(json_en code(阵列('验证'=>真,'消息'=> __('您已经登录成功'))));
        }
        其他
        {
            $这个 - > autoRender = FALSE;
            $这个 - >&响应 - GT;类型('JSON');
            $这个 - >&响应 - GT;机身(json_en code(阵列('验证'=>假的,'消息'= GT; __(用户名或密码不正确'))));
        }    }
    其他
    {
        $这个 - > autoRender = FALSE;
        $这个 - >&响应 - GT;类型('JSON');
        $这个 - >&响应 - GT;机身(json_en code(阵列('信息'=>'GET请求不允许的!')));
    }
}

移动设备(或API的用户)可以将自己的登录信息,然后他们获得请求的JSON为真或假的认证。的这个布尔不是用来给用户的访问,它,而不是告诉移动应用程序,如果他们能看到某些屏幕,他们只获取数据,或如果会话存在,可以将数据发送!

正如刚才所说,他们也实际登录到API本身的装置上,所以,如果他们直接访问网站(从设备),他们将有一个会议,看到了JSON同样的反应。

所以基本上,用户保持登录他们与服务器通信的设备上的会话的持续时间。这是这将需要传递的每个请求,其中如在此例子中,它们有一个会话令牌不同

现在问题...


  1. 它是实践的用户是坏实际上登录到API
    与会话如上所示?这似乎是因为它使用了相同的逻辑直接Web根来处理身份验证设备最安全的方法。


  2. 我已经看到了一些API使用的访问令牌,而不是我以前也
    实施(用户得到他们的令牌返回的布尔值,而不是
    没有会话创建)。但是,从我可以告诉,这似乎
    像更多的工作是那么我需要检查对访问令牌
    用户记录每一个发出请求的时间。



解决方案

修改结果
为了清楚起见,我不是REST的支持者,我的REST风格/ RESTlike服务的支持者。如果你看所有的互联网上的API,很少真正坚持一个标准。无论方案您选择将取决于您的具体问题的空间。只是尽量是安全的,使用直观的设计选择(即不命名服务猫,如果它返回有关狗的信息)结果
年底修改

这是基于REST的API的好做法来管理的部分的形式会话/标记化方案。真正理想的(至少在我看来,有在这个问题上的思想很多学校)设置包括滚动令牌。

如果你是在所有关心你的API的安全,然后权限应出你的数据库层管理。是的,这产生了一个瓶颈,但实际上是一件好事。孤男寡女打数据库每一次来验证客户端的令牌增加在整个过程中额外的步骤。这会减慢API,它是在一个安全的系统实际上desireable。你不想恶意个人能打到你的API 3000次第二,您希望自己的请求挂起第二的(有点)相当大的部分。

这是类似于 MD5 散列算法。他们中的许多重新计算散列几百倍,在两者之间随机暂停。这有助于保持一个恶意用户通过尝试暴力破解密码(通过使它需要更多的时间来测试密码字符串的每个变化)。这同样适用于你的API。

另一个好处是,如果你的 DO 的有恶意用户试图在一遍遍再次登录,如果从数据库层管理它们,那么你就可以红旗自己的IP地址/用户名/什么具备的,你,只是在步骤1中放弃他们的请求。

总之,对于一个建议的过程(与滚动令牌,可以切出这个部分,如果它似乎矫枉过正,但是这是海拉安全):


  1. 用户点击登录服务,这需要用户名/密码,并返回两个令牌,一个私人访问令牌和一个公共请求令牌(服务器存储这些标记的分贝)。

  2. 客户端存储这些令牌在安全的地方

  3. 用户访问另一个端点推/拉一些数据

    • 请求包括时间戳

    • 请求包括公共请求令牌

    • 请求包括访问令牌=>此标记应该从串联时间戳字符串私人访问令牌字符串的结尾
    • 生成字符串的MD5哈希

  4. 服务器采用公共请求令牌,使用该查找已存储的私人访问令牌

    • 的服务器采用的私人访问令牌,并在时间戳字符串会连接,然后又把这个字符串的MD5

    • 如果新的访问令牌匹配的客户端发送服务器,华友世纪,此客户端验证的一个,所以推/拉数据


  5. (可选)服务器上生成每个请求新的令牌,并返回给客户端。这样,每一笔交易的老令牌无效,并且如果有某种中间人攻击发生,如果有效用户已经完成了他们的请求,恶意用户现在有一些错误的记号而无法启动搞乱您的API。该方案试图确保恶意用户不能指望拦截服务器和客户端之间的单个通信,并且仍然获得系统。如果他们这样做,那么真正的用户应该立即得到无效的令牌。那么这应该引起他们的API客户端,再次点击登录服务,获得新的有效令牌。这再次踢恶意用户从系统中。

这方案不是100%安全,无用户访问系统永远不会是。它可以通过在令牌添加过期日期进行更加安全。该方案也有额外的好处,你可以分配给用户/标记特定的权限(即只读访问,只有特定端点可以看出,等)

这是不是你可以做的事情的唯一途径,我会查找其他身份验证方案,并把你从他们每个人( OAUTH 是一个良好的开端,那么我想看看Facebook的/微博/ Instagram的)

I have built a simple test API for a CakePHP application that will let a user login from a mobile device (or any device for that matter) and get a JSON response. This API could be used for a mobile app built in PhoneGap.

The login method looks like so:

public function login()
{
    if($this->request->is('post'))
    {
        // Use custom method in Model to find record with password params
        $findUser = $this->User->findUser(
            $_POST['username_or_email'],
            AuthComponent::password($_POST['password'])
        );

        // If a user exists and matches params
        if($findUser)
        {                           
            $this->User->id = $findUser['User']['id'];

            $this->autoRender = false;
            $this->response->type('json');
            $this->response->body(json_encode(array('authenticated'=>true,'message'=>__('You have been logged in successfully'))));
        }
        else
        {
            $this->autoRender = false;
            $this->response->type('json');
            $this->response->body(json_encode(array('authenticated'=>false,'message'=>__('Username or password is incorrect'))));
        }

    }
    else
    {
        $this->autoRender = false;
        $this->response->type('json');
        $this->response->body(json_encode(array('message'=>'GET request not allowed!')));
    }
}

The mobile device (or any API user) can send their login details and then they get the request as JSON as true or false for authenticated. This boolean is NOT used to give the user access, it instead tells the mobile app if they can see certain screens and they ONLY get the data or can send data if the session exists!

As just stated, they are also actually logged into the API itself on the device so if they visit the website directly (from that device) they will have a session and see the same response for the JSON.

So essentially a user remains logged in for the duration of the session on the device they communicated with the server on. This is different to a token which would need to be passed for every request, where as in this example they have a session.

Now the questions...

  1. Is it bad practice for the user to be 'actually' logged into the API with a session like shown above? It seems like the most secure way to handle authentication for a device as it's using the same logic as the direct web root.

  2. I've seen some APIs use access tokens instead which I've also implemented (user gets their token returned instead of the boolean and no session is created). But from what I can tell, this seems like more work as then I need to check for the access token against a user record every time a request is made.

解决方案

edit
For the sake of clarity, I am not a supporter of REST, I AM a supporter of RESTful/RESTlike services. If you look at all of the API's on the internet, very few actually stick to one standard. Whatever scheme you choose will depend on your specific problem-space. Just try to be secure and use intuitive design choices (ie dont name a service "cats" if it returns info about "dogs")
end edit

It is good practice in RESTful API's to manage some form of session/tokenizing scheme. Really the ideal (at least in my opinion, there are many schools of thought on this problem) setup involves rolling tokens.

If you are at all concerned with the security of your API, then permissions should be managed out of your database layer. Yes, this creates a bottleneck, BUT THAT IS ACTUALLY A GOOD THING. Needing to hit the database every single time to validate a client's token adds an extra step in the entire process. This slows down the API, which is actually desireable in a secure system. You don't want a malicious individual to be able to hit your API 3000 times a second, you want their requests to hang for a (somewhat) sizeable fraction of a second.

This is similar to MD5 hashing algorithms. Many of them recalculate the hash a few hundred times, with random pauses in between. This helps to keep a malicious client from attempting to brute force a password (by making it take more time to test each variation of the password string). The same applies to your API.

The other benefit, is that if you DO have a malicious user trying to log in over and over again, if you are managing them from the database layer, then you can red flag their IP Address/username/what-have-you and just drop their requests at step 1.

Anyway, for a suggested process (with rolling tokens, you can cut out parts of this if it seems overkill, but this is hella secure):

  1. User hits a 'login' service, this requires a username/password, and returns two tokens, a Private Access Token and a Public Request Token (the server stores these tokens in the db).
  2. The client stores these Tokens in a secure place
  3. User accesses another endpoint to push/pull some data
    • Request includes a timestamp
    • Request includes the Public Request Token
    • Request includes an Access Token=> This token should be a MD5 hash of the string resulting from concatenating the timestamp string to the end of the Private Access Token string
  4. The server takes the Public Request Token, uses that to lookup the Private Access Token that was stored
    • The server takes that Private Access Token, and concatenates on the Timestamp String, it then takes the MD5 of this string
    • If the new Access Token matches the one that the client sent the server, HURRAY, this client is validated, so push/pull the data
  5. (Optional) The server generates new tokens on every request, and returns them to the client. This way every transaction invalidates the old tokens, and if there was some kind of man-in-the-middle attack occurring, if the VALID user has already completed their request, the malicious user now has invalid tokens and can't start messing with your API. This scheme tries to ensure that a malicious user can not expect to intercept a single communication between the server and the client, and still gain access to the system. If they do, then the REAL user should immediately get invalidated tokens. Which should then trigger their API client to hit the 'login' service AGAIN, getting new valid tokens. This once again kicks the malicious user out of the system.

This scheme is not 100% secure, no user access system ever will be. It can be made more secure by adding expiration dates on tokens. This scheme also has the added benefit that you can assign specific permissions to users/tokens (ie Read-Only access, only certain End-Points can be seen, etc)

This is not the only way you can do things, I would look up other Authentication Schemes and take what you want from each of them (OAUTH is a good place to start, then I'd look at Facebook/Twitter/Instagram)

这篇关于使用会话VS令牌API认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆