怎么使用slim-jwt-auth对API进行身份验证

这两天一直想找个机会做一下API的身份验证,就像微博那样提供接口给别人用,但又有所限制,也不会导致接口滥用。 大概一年半之前,写了个大学英语四六级成绩查询的接口(由于历史原因,此Github帐号不再使用了,新的在这里),托管在新浪云,放到了网上,也没有加任何限制,结果被一个人短时间内多次调用,真的是非常频繁,浪费了不少云豆。现在正好可以用之前写的成绩查询接口来做这个身份验证的实验。

准备工作

在做一个二维码签到/点名系统时,需要后台同时支持移动端、PC端和网页版,因此决定写成接口,这样比较方便。既然写成接口,就写的规范一些咯,之前自己写的小玩意实在是拿不出手,毫无规范可言。了解到RESTful API,查了一些资料,主要看了这篇, 写的很不错。然后就去找个框架呗。 在写二维码签到/点名系统时,用的是CI框架,也有第三方的REST库, 但用的很不爽,说不上来的不得劲。经过查询,知道了slim这个框架,是专门构建RESTful API的框架。之后就开始了一天的折腾。

安装框架和用到的第三方组件

官方推荐使用composer进行安装,下面不说废话了,Come on Install composer Slim and some third plugins

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer        // install composercomposer require slim/slim "^3.0"        // install Slimcomposer require tuupola/slim-basic-auth "^2.0"        // install slim-basic-authcomposer require lcobucci/jwt "^3.1"        // install jwtcomposer require tuupola/slim-jwt-auth "^2.0"        // install slim-jwt-auth

啰嗦一句,windowns上面进行开发比较麻烦,建议装个虚拟机跑ubuntu/cenos或者你喜欢的发行版

开始码

需要注意的是,当前(2015年12月21日)时间,slim最新版本是3.0 开始之前我找了一些网上别人写的中文入门之类的博文,但大多是2.x, 会有一些坑(不禁想起了Python的版本, o(︶︿︶)o ).

根据我已经写完了的V1的示例代码来分析/学习 index.php: https://github.com/xu42/API/blob/master/index.php cet_score.php: https://github.com/xu42/API/blob/master/v1/cet_score/cet_score.php

  • Authentication Process (身份验证流程)
    • 假定使用我们的接口的人(以下称”客户”)已经注册成为会员,已经拥有获取接口使用权限的”username” 和 “password”
    • 客户向后台发送附带”username” 和 “password” 和 “key” 的请求, 请求获取接口使用权的”accecc_token”
    • 客户拿到”accecc_token”后, 向成绩查询接口发起请求同时附带”access_token”和”key”
    • 后台验证并返回相应的结果
  • Specific analysis (具体分析)
    • 定义获取”access_token”的URL是”https://ip/token“, 除了这个URL其它都应该需要验证身份。在Github上查看代码 123456789101112$app->add(new JwtAuthentication([ "secret" => "cn.xu42.api", "rules" => [ new JwtAuthentication\RequestPathRule([ "path" => '/', "passthrough" => ["/token"] ]) ], "callback" => function(ServerRequestInterface $request, ResponseInterface $response, $arguments) use ($app) { $app->jwt = $arguments["decoded"]; }]));
    • 这一步的验证是”Basic Auth”方式(已经很少有再用”Basic Auth”了, 因为有更好的”OAuth 2.0”替代), 因为是个示例, 直接把”username” 和 “password”写死在了代码里, 规模大了应该写在数据库里。在Github上查看代码 123456$app->add(new HttpBasicAuthentication([ "path" => "/token", "users" => [ "user0" => "user0password" ]]));
    • 客户向 https://ip/token 发起GET 请求, 后台生成”access_token”。在Github上查看代码 123456789101112131415161718$app->get("/token", function(ServerRequestInterface $request, ResponseInterface $response, $arguments) use ($app) { if(!$request->hasHeader('key')){ return $response->withStatus(401); } $access_token = (new Builder())->setIssuer('https://api.xu42.cn') // Configures the issuer (iss claim) ->setAudience('https://api.xu42.cn') // Configures the audience (aud claim) ->setId($request->getHeaderLine('key'), true) // Configures the id (jti claim), replicating as a header item ->setIssuedAt(time()) // Configures the time that the token was issue (iat claim) ->setNotBefore(time()+60) // Configures the time that the token can be used (nbf claim) ->setExpiration(time()+3600) // Configures the expiration time of the token (exp claim) ->set('scope', ['read']) // Configures a new claim, called "scope" ->sign(new \Lcobucci\JWT\Signer\Hmac\Sha256(), 'cn.xu42.api') // ALGORITHM HS256 ->getToken(); // Retrieves the generated token $response = $response->withStatus(200); $response = $response->withHeader('Content-type', 'application/json'); $response->getBody()->write(json_encode(['access_token' => (string) $access_token, 'token_type' => 'bearer', 'expires_in' => $access_token->getClaim('exp') - $access_token->getClaim('iat')])); return $response;});
    • 客户请求成绩查询接口, 需要验证”access_token” 和 “key”, 并返回结果。在Github上查看代码 12345678$app->get('/v1/cet_score/{name}/{numbers}', function (ServerRequestInterface $request, ResponseInterface $response, $args) use ($app) { if(in_array('read', $app->jwt->scope) && $app->jwt->jti == $request->getHeaderLine('key')) { require_once 'v1/cet_score/cet_score.php'; return cet_score::get($request, $response, $args); } else { return $response->withStatus(401); }});

整个流程就是这样,不难,代码量也不大,第一次完成了还像样的接口,还是挺高兴的。但也明白,这跟真实企业级的接口比,差的还很远,继续努力。

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java进阶干货

Tomcat中用JNDI方式加载JDBC DataSource以连接数据库

下载与所要连接的数据库版本对应的JDBC驱动程序,加入到应用的CLASSPATH。如果用tomcat部署,tomcat中最好也加上(笔者觉得好像没必要加,可是不...

1602
来自专栏phodal

后端技能清单(草稿)

昨天也顺手整理了一下我所需要的后端技能清单。不过,由于我离非常有经验的后端开发者有点距离,希望大家可以给点意见哈。 入门 HTML / CSS 编程语言:Ja...

2125
来自专栏Phoenix的Android之旅

Android8.0的广播-熟悉的陌生人

Android 8.0正式版上线到现在已经有一年了,很多厂商的2018年的机型上已经用上了这个系统。

1062
来自专栏Hadoop实操

如何在CDH中安装和使用StreamSets

StreamSets由Informatica前首席产品官Girish Pancha和Cloudera前开发团队负责人Arvind Prabhakar于2014年...

6.9K10
来自专栏信安之路

锁首技术总结

在公司实习也有一个月了,学到不少东西,不知不觉就要大四了,回首漫漫安全路,不禁感慨万千:我入安全的时间比较晚,大一大二跟着老师参加 Android 移动应用开发...

1232
来自专栏FreeBuf

没有身份凭证的情况下,攻击者就能登录FreeRADIUS

近期,来自卢森堡RESTENA的安全研究专家Stefan Winter在当前全球最流行的radius服务器中发现了一个TLS认证绕过漏洞。 ? FreeRADI...

2789
来自专栏小文博客

百度云破限速(安卓+Windows)

9.3K3
来自专栏gaoqin31

Linux 的账号与群组

理员的工作中,相当重要的一环就是『管理账号』啦!因为整个系统都是你在管理的, 并且所有一般用户的账号申请,都必须要透过你的协助才行!所以你就必须要了解一下如何管...

1311
来自专栏FreeBuf

更适合作为主系统使用的Parrot Security简介

Parrot 是一个基于Debian的专注于渗透测试和隐私保护的Linux发行版,但是更加方便日常使用,有贴心的使用体验,丰富的工具,更注重隐私保护。 The...

8485
来自专栏FreeBuf

年度盘点 | 安全测试者偏爱的安全测试工具

国外网站Concise Courses总结了安全测试者常用且好用的安全测试工具,本文摘录并分类整理列举一二,供安全从业者与爱好者参考。 ? 无线类 Metasp...

4977

扫码关注云+社区

领取腾讯云代金券