使用Token来做身份认证在目前的移动客户端上非常流行,Token这个概念来源于OAuth认证,主要是在服务端实现。关于相关的原理,同学们自行百度。在这里,我简单介绍一下我是怎么具体实现的,重点描述token生成、token识别及token缓存。

生成Token

服务端接收客户端传递的username和password等请求,在数据库中检查,如果用户名密码匹配的话,表示登录成功,服务端生成并返回一个token访问令牌。

  1. public function login()
  2. {
  3. $data = array_merge($this->request->post(), []);
  4. // login with password
  5. $user = Db::name($this->table)->field($this->field_except, true)->where('name', $data['name'])->find();
  6. if ($user) {
  7. if ($user['pwd'] === EncryptService::password($data['pwd'])) {
  8. $this->onLoginSuccess($user);
  9. } else {
  10. parent::logic_failure('密码不正确', 'user_wrong_pwd');
  11. }
  12. } else {
  13. parent::logic_failure('用户不存在', 'user_not_exists');
  14. }
  15. }
  16. private function onLoginSuccess($user)
  17. {
  18. unset($user['pwd']);
  19. $token = Token::generateToken($this->request, $user);
  20. $ret = [
  21. 'token' => $token['token'],
  22. 'user' => $user
  23. ];
  24. $this->logic_success(null, $ret);
  25. }

在上面的代码中,登录成功,服务端向客户端返回token和user信息。token是通过Token类的静态方法generateToken来生成的。

  1. public static function generateToken($request, $user)
  2. {
  3. // 1,生成包含用户及设备信息的新token
  4. $data = [
  5. 'uuid' => $request->param('uuid', ''),
  6. 'uid' => $user['id'],
  7. 'ip' => $request->ip(),
  8. 'client' => $request->param('client', ''),
  9. 'update_time' => ApiBase::_timestamp(),
  10. ];
  11. // json序列化
  12. $json = json_encode($data);
  13. // 加密token信息
  14. $key = md5(EncryptService::encrypt($json));
  15. $data['token'] = $key;
  16. // 2,从数据库查询用户的token,决定是update还是insert
  17. $token = Token::get($user['id']);
  18. // 如果数据库中已存在token,更新
  19. if ($token) {
  20. // 删除旧的缓存
  21. cache($token['token'], null);
  22. // 执行更新
  23. $token->isUpdate(true)->save($data);
  24. }
  25. // 不存在,插入
  26. else {
  27. $token = new Token();
  28. $data['create_time'] = ApiBase::_timestamp();
  29. $token->data($data)->save();
  30. }
  31. // 3,将token写入缓存
  32. Token::cacheToken($token->getData());
  33. return $token->getData();
  34. }

这里主要有3个步骤

  1. 根据用户及设备等信息生成一个唯一的token,uid用于识别用户,uuid用于识别设备,time用于保证唯一。将这些信息序列化后加密并生成md5
  2. 根据用户id查询用户登录表,不管用户原来是否已经存在token,新的token将替换旧的token
  3. 将token写入缓存,因为token是每个请求都会解析,如果不使用缓存的话,会导致数据库访问瓶颈。

客户端应该保存token,然后在访问一些需要身份认证的API,比如修改昵称,就需要带上这个token了,而不需要显示带上用户信息,比如user_id。

解析token

服务端接收客户端传递的token,需要从中解析出相关的用户及设备信息。

  1. public static function getToken($key)
  2. {
  3. if (!isset($key)) {
  4. return null;
  5. }
  6. $token = cache($key);
  7. if ($token) {
  8. return $token;
  9. }
  10. else {
  11. return Token::findByToken($key);
  12. }
  13. }

过程很简单,先从缓存中取,如果不存在再从数据库中查询。所有的请求,服务端都会执行解析token。

验证token

服务端简单地把API分为三类

  1. 公共API,客户端可以任意访问,不需要验证身份,此类API多以GET请求为多。比如查询产品列表
  2. 受保护的API,也即需要强制认证的API,这类API需要验证客户端身份才能访问,比如修改头像,客户端未传token或token无效,服务端返回一个错误码。
  3. 可选认证的API,介于1和2之间,不要求强制验证客户端身份,比如分享奖励,如果客户端传递了token并认证通过了,则给相应的奖励,否则不做任何的奖励。

基于上面的分析,验证token附带一个是否强制验证的参数,用于中断。验证的规则也相对简单,只要用户请求的设备ID与token中的设备ID相同就算验证通过了。

  1. public function checkToken($exit = true)
  2. {
  3. if ($this->token) {
  4. if ($this->token['uuid'] === $this->request->param('uuid', '')) {
  5. return true;
  6. } else {
  7. if ($exit) {
  8. $this->logic_failure(null, 'user_offline');
  9. } else {
  10. $this->token = null;
  11. }
  12. return false;
  13. }
  14. } else {
  15. if ($exit) {
  16. $this->logic_failure(null, 'token_invalid');
  17. }
  18. return false;
  19. }
  20. }

缓存

缓存相对简单,缓存的key为加密token之后的md5值,也即登录成功后,服务端向客户端发送的token值。缓存未设置有效期,默认永不过期。

  1. public static function cacheToken($token)
  2. {
  3. if ($token) {
  4. if (is_object($token)) {
  5. $token = $token->getData();
  6. }
  7. cache($token['token'], ($token));
  8. }
  9. }
  10. ?>

进阶

为了让您的应该更加安全,还可以在以下方面强化

  1. token有效期
  2. token缓存加密
  3. token高级校验

不过,我这里已经对token做了对称加密,相信他人伪造token的可能性也不大。

作者:Jamling
链接:https://www.jianshu.com/p/8a75d727e252
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

我是怎么做App token认证的的更多相关文章

  1. 我是这样做APP的:击中用户的痛点(转)

    击中用户的痛点 点评,感觉取名叫做“用户痛点的取舍”更加合适.很多公司.项目的失败完全取决于决策人取舍的失败,一味地追求大而全.迎合上级领导,专断而没有和团队做客观的分析.本文虽然以一个应该来说并不复 ...

  2. 基于Token认证的多点登录和WebApi保护

    在文章中有错误的地方,或是有建议或意见的地方,请大家多多指正,邮箱: linjie.rd@gmail.com 一天张三,李四,王五,赵六去动物园,张三没买票,李四制作了个假票,王五买了票,赵六要直接F ...

  3. laravel5.7 前后端分离开发 实现基于API请求的token认证

    最近在学习前后端分离开发,发现 在laravel中实现前后台分离是无法无法使用 CSRF Token 认证的.因为 web 请求的用户认证是通过Session和客户端Cookie的实现的,而前后端分离 ...

  4. Token认证登录以及权限控制

    IdentityServer4实现Token认证登录以及权限控制   相关知识点 不再对IdentityServer4做相关介绍,博客园上已经有人出了相关的系列文章,不了解的可以看一下: 蟋蟀大神的: ...

  5. 【翻译】asp.net core2.0中的token认证

    原文地址:https://developer.okta.com/blog/2018/03/23/token-authentication-aspnetcore-complete-guide token ...

  6. flask token认证

    在前后端分离的项目中,我们现在多半会使用token认证机制实现登录权限验证. token通常会给一个过期时间,这样即使token泄露了,危害期也只是在有效时间内,超过这个有效时间,token过期了,就 ...

  7. python 全栈开发,Day97(Token 认证的来龙去脉,DRF认证,DRF权限,DRF节流)

    昨日内容回顾 1. 五个葫芦娃和三行代码 APIView(views.View) 1. 封装了Django的request - request.query_params --> 取URL中的参数 ...

  8. PHP做APP接口时,如何保证接口的安全性??????????

    PHP做APP接口时,如何保证接口的安全性? 1.当用户登录APP时,使用https协议调用后台相关接口,服务器端根据用户名和密码时生成一个access_key,并将access_key保存在sess ...

  9. 关于vue跨域名对接微信授权认证和APP授权认证

    这种情况一般也只会出现在前后端分离,跨域名授权的时候吧.耗费了一个前端+一个后台+一个网关,熬夜通宵了两天才整出来一套方法(你们见过凌晨6点的杭州吗,对,我下班的时候天黑了,到家天亮了....),和开 ...

随机推荐

  1. 内存问题检查利器——Purify

    内存问题检查利器——Purify 一.           引言 我们都知道软件的测试(在以产品为主的软件公司中叫做QA—Quality Assessment)占了整个软件工程的30% -50%,但有 ...

  2. hdu 1506 Largest Rectangle in a Histogram ((dp求最大子矩阵))

    # include <stdio.h> # include <algorithm> # include <iostream> # include <math. ...

  3. 关于Android中设置闹钟的相对完善的解决方案

    前些时候,有人在我「非著名程序员」微信公众号的后台问我有没有设置闹钟的demo,我当时说承诺为大家写一个,一直没空,直到最近又有人跟我要,我决定抽时间写一个吧.确实设置闹钟是一个比较麻烦的东西.我在这 ...

  4. java导出word直接下载

    导出word工具类 package util; import java.io.IOException; import java.io.Writer; import java.util.Map; imp ...

  5. ArcSDE:C#打开SDE数据库的几种方式总结

    转自原文 ArcSDE:C#打开SDE数据库的几种方式总结 1.通过指定连接属性参数打开数据库 /// <param name="server">数据库服务器名< ...

  6. [RxJS] Use takeUntil instead of manually unsubscribing from Observables

    Manually unsubscribing from subscriptions is safe, but tedious and error-prone. This lesson will tea ...

  7. LUA凝视语法

    server端代码已经完毕,client正在优化.游戏不久将上线,近期没事做,老大要我開始学习project Anarchy了.里面代码是比較偏爱的C++,包括lua,暂没学过lua.看了下LUA代码 ...

  8. error C2220: warning treated as error - no 'object' file generated warning C4819: The file contains a character that cannot be represented in the current code page (936).

    用Visual Studio2015 编译时,遇到如下编译错误: error C2220: warning treated as error - no 'object' file generated ...

  9. python3报错

    这个错误是我在从Excel中导入数据,,x,y 和z(z代表了强度)  然后通过xyz画出一个二维的灰度图片所出现的错误 原因是因为用mcml生成的数据如: TypeError: cannot per ...

  10. System.ComponentModel.Win32Exception (0x80004005):拒绝访问。——解决办法

    一.问题如下: (无法执行程序.所执行的命令为 "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /noconfi ...