URL与控制器 - 请求拦截与权限控制

优质
小牛编辑
132浏览
2023-12-01

EasySwoole支持在三个地方进行请求拦截,当一个HTTP请求进来,EasySwoole的执行先后顺序是:

  • Event中的OnRequest事件
  • 自定义路由(可选)
  • 控制器中的OnRequest

在以上任意位置执行 $response->end(),均不会进入下一个流程。

权限验证拦截

例如我现在 /Api/Mobile 下的全部控制器,均需要做权限控制,那幺我们先建立一个全局的抽象控制器。

  1. abstract class AbstractBase extends AbstractController
  2. {
  3. protected $who;
  4. function onRequest($actionName)
  5. {
  6. // TODO: Implement onRequest() method.
  7. $cookie = $this->request()->getCookieParams(SysConst::WX_USER_COOKIE_NAME);
  8. if(empty($cookie)){
  9. $this->response()->writeJson(Status::CODE_UNAUTHORIZED);
  10. $this->response()->end();
  11. }else{
  12. $info = Redis::getInstance()->getConnect()->hGet(SysConst::REDIS_USER_INFO,$cookie);
  13. if(is_array($info)){
  14. if(time() - $info['time']< SysConst::WX_USER_COOKIE_TTL){
  15. $this->who = $info['userBean'];
  16. }else{
  17. $this->response()->writeJson(Status::CODE_UNAUTHORIZED);
  18. $this->response()->end();
  19. }
  20. }else{
  21. $this->response()->writeJson(Status::CODE_UNAUTHORIZED);
  22. $this->response()->end();
  23. }
  24. }
  25. }
  26. function actionNotFound($actionName = null, $arguments = null)
  27. {
  28. // TODO: Implement actionNotFound() method.
  29. $this->response()->withStatus(Status::CODE_NOT_FOUND);
  30. }
  31. function afterAction()
  32. {
  33. // TODO: Implement afterAction() method.
  34. }
  35. }

而后,我/Api/Mobile下的任意一个控制器,仅需继承该方法,即可实现权限控制。

  1. namespace AppControllerApiMobile;
  2. class Index extends AbstractBase
  3. {
  4. function index()
  5. {
  6. // TODO: Implement index() method.
  7. $this->response()->write($this->who->getOpenId());
  8. }
  9. }

全局请求安全过滤拦截

例如,项目上线后,由于前期开发未注意安全问题,没有做参数过滤,那幺,可以在Event中的OnRequest事件,进行全局的请求参数过滤或者拦截。

建立测试拦截类

  1. namespace AppUtility;
  2. class Security
  3. {
  4. /*
  5. * 本注入脚本从网上流传的360 php防注入代码改版 仅供做参考
  6. */
  7. private $getFilter = "'|(and|or)\b.+?(>|<|=|in|like)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
  8. private $postFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
  9. private $cookieFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
  10. function check(array $data){
  11. foreach ($data as $item){
  12. if (preg_match("/".$this->getFilter."/is",$item) == 1){
  13. return true;
  14. }
  15. if (preg_match("/".$this->postFilter."/is",$item) == 1){
  16. return true;
  17. }
  18. if (preg_match("/".$this->cookieFilter."/is",$item) == 1){
  19. return true;
  20. }
  21. }
  22. return false;
  23. }
  24. }

在onRequest事件中调用

  1. function onRequest(Request $request, Response $response)
  2. {
  3. // TODO: Implement onRequest() method.
  4. $sec = new Security();
  5. if($sec->check($request->getRequestParam())){
  6. $response->write("do not attack");
  7. $response->end();
  8. return;
  9. }
  10. if($sec->check($request->getCookieParams())){
  11. $response->write("do not attack");
  12. $response->end();
  13. return;
  14. }
  15. }

EasySwoole也支持用户使用session。

注意:以上代码仅仅做逻辑展示,请勿直接使用。