基于令牌的身份验证中的会话

Fla*_*dun 20 php jquery authorization reactjs lumen

我正在PHP Lumen中构建一个应用程序,它在登录时返回一个令牌.我不知道如何超越这个.

我该如何使用这些令牌维护会话?

具体来说,如果我使用reactjs或vanilla HTML/CSS/jQuery,如何在我为Web应用程序的安全部分发出的每个请求中发送它们,如何在客户端存储令牌?

Cry*_*fel 12

我通常做的是将令牌保留在本地存储中,这样即使用户离开站点,我也可以保留令牌.

localStorage.setItem('app-token', theTokenFromServer);
Run Code Online (Sandbox Code Playgroud)

每次用户加载页面时,我要做的第一件事就是查找令牌的存在.

token = localStorage.getItem('app-token');
Run Code Online (Sandbox Code Playgroud)

如果使用react,我会将令牌保持在全局状态(例如使用redux):

function loadAppToken(token) {
  return {
    type: 'LOAD_TOKEN',
    payload: { token },
  };
}
Run Code Online (Sandbox Code Playgroud)

使用vanilla javascript,我会将它保存在我的连接实用程序中.这可能类似于以下内容:

const token = localStorage.getItem('app-token');

export function request(config) {
   const { url, ...others } = config;

   return fetch(url, {
     ...others,
     credentials: 'include',
     headers: {
       'Authorization': `Bearer ${token}`
     },
   });
}
Run Code Online (Sandbox Code Playgroud)

我在react应用程序中仍然有一个fetch实用程序,类似于前面的代码,但我会在选项中发送令牌,通过在每个请求的redux中间件中获取它.


小智 5

假设您要构建一个APP。

  1. ReactJS
  2. REST API与PHP
  3. 使用JWT

1.简介

构建REST API时,您必须忘记会话。

REST API是无状态的,因此它们不能依赖于会话,它们只能使用客户端提供的数据来处理请求。

2.认证

客户要做的只是交换一些username&代password币。

这是一个HTTP请求示例

POST /api/v1/authentication HTTP/1.1
Host: localhost
Content-Type: application/json
{
    "username": "foo",
    "password": "bar"
}
Run Code Online (Sandbox Code Playgroud)

响应是:

{
    "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Run Code Online (Sandbox Code Playgroud)

3.让我们进入请求/响应的更多细节

我们的API将如何处理身份验证请求?

  1. 它将检查是否创建了具有用户名foo和密码的用户,并且该用户bar在数据库中处于活动状态

  2. 它将生成一个JWT(Json Web令牌)

  3. 它将返回包含JWT的响应

例如,这是一些超级简单的auth方法。

public function authAction()
{
  /** Get your payload somehow */
  $request = $_POST;

  //Validate if username & password are given/

  $user = $this->model->auth($username, $password);

  if(!$user) {
    //throw error for not valid credentials
  }

  $jwt = $this->jwt->create($user);

  //return response with $jwt
}
Run Code Online (Sandbox Code Playgroud)

如您所见,它们没有设置会话或任何会话。

我们的客户端将如何处理响应?

客户端可以使用诸如superagent之类的软件包来处理对我们API的请求和响应,从而将过程简化为:

  let data = {
    username: email,
    password: password
  };

  request
    .post('/api/v1/authentication')
    .set('Content-Type', 'application/json')
    .send(data)
    .end(function (error, response) {
      //response.body.token
    });
Run Code Online (Sandbox Code Playgroud)

4.在服务器端创建JWT

您可以使用某些3RD PT软件包来生成验证 JWT,而不必自己编写。

查看此软件包,您可以看到它是如何完成的。

并记住要始终创建有力的签名。我建议使用RSA keys

我并不是在宣传或支持这个项目,只是在这里分享它很有用。我从未使用过它,我在NodeJS项目中使用了类似的东西。

5.在客户端保存JWT

您已经知道这是两种方式localStoragecookies 对我来说,我正在使用Cookie,因为:

  1. 它们更加安全
  2. 可以设置过期日期,而无需实现某些自定义逻辑。
  3. 较旧的浏览器支持(非常旧的浏览器,因此并不重要)。

但这完全取决于您。

6.使用JWT

从现在开始,对服务器的每个请求都必须包括JWT。

在REST API中,您必须编写一种方法来验证JWT并将其交换为用户对象。

请求示例:

  let jwt = ...; //GET IT FROM LOCALSTORAGE OR COOKIE

  request
    .get('/api/v1/posts')
    .set('Content-Type', 'application/json')
    .set('Authorization', jwt)
    .end(function (error, response) {

    });
Run Code Online (Sandbox Code Playgroud)

API如何处理此请求

public function postsAction()
{
  $jwt = $this->headers->get('Authorization');

  if(!$this->jwt->validate($jwt)) {
    //throw unauthorized error
  }

  $user = $this->model->exchangeJWT($jwt);

  //Your logic here
}
Run Code Online (Sandbox Code Playgroud)

7.到期日期和Cookie

如果您使用cookie来保存您的JWT,请谨慎设置过期日期。

Cookie的到期日期必须等于JWT的到期日期。