src/AppBundle/Controller/BaseController.php line 453

Open in your IDE?
  1. <?php
  2. namespace AppBundle\Controller;
  3. use AppBundle\Common\ArrayToolkit;
  4. use AppBundle\Common\Exception\AbstractException;
  5. use AppBundle\Common\Exception\ResourceNotFoundException;
  6. use AppBundle\Common\JWTAuth;
  7. use Biz\Common\CommonException;
  8. use Biz\QiQiuYun\Service\QiQiuYunSdkProxyService;
  9. use Biz\System\Service\SettingService;
  10. use Biz\User\CurrentUser;
  11. use Codeages\Biz\Framework\Service\Exception\AccessDeniedException;
  12. use Firebase\JWT\JWT;
  13. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  14. use Symfony\Component\Form\Extension\Core\Type\FormType;
  15. use Symfony\Component\HttpFoundation\JsonResponse;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpFoundation\Response;
  18. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  19. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  20. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  21. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  22. use Symfony\Component\Security\Http\SecurityEvents;
  23. class BaseController extends Controller
  24. {
  25.     /**
  26.      * @return CurrentUser
  27.      */
  28.     protected function getCurrentUser()
  29.     {
  30.         return $this->getUser();
  31.     }
  32.     protected function getBiz()
  33.     {
  34.         return $this->get('biz');
  35.     }
  36.     /**
  37.      * @return CurrentUser
  38.      */
  39.     public function getUser()
  40.     {
  41.         $biz $this->getBiz();
  42.         return $biz['user'];
  43.     }
  44.     /**
  45.      * switch current user.
  46.      *
  47.      * @return CurrentUser
  48.      */
  49.     protected function switchUser(Request $requestCurrentUser $user)
  50.     {
  51.         $user['currentIp'] = $request->getClientIp();
  52.         $token = new UsernamePasswordToken($usernull'main'$user['roles']);
  53.         $this->container->get('security.token_storage')->setToken($token);
  54.         $biz $this->getBiz();
  55.         $biz['user'] = $user;
  56.         $this->get('event_dispatcher')->dispatch(SecurityEvents::INTERACTIVE_LOGIN, new InteractiveLoginEvent($request$token));
  57.         // $this->getLogService()->info('user', 'user_switch_success', '用户切换登录成功');
  58.         return $user;
  59.     }
  60.     protected function prepareLimitedTime($limitedTime 0)
  61.     {
  62.         $limitedTime ltrim($limitedTime0);
  63.         if (empty($limitedTime)) {
  64.             return 0;
  65.         }
  66.         return $limitedTime;
  67.     }
  68.     protected function authenticateUser(array $user)
  69.     {
  70.         $user['currentIp'] = $this->container->get('request_stack')->getCurrentRequest()->getClientIp();
  71.         $currentUser = new CurrentUser();
  72.         $currentUser->fromArray($user);
  73.         $currentUser $this->switchUser($this->get('request_stack')->getCurrentRequest(), $currentUser);
  74.         $this->checkLoginPasswordUpgraded($currentUser$this->get('request_stack')->getCurrentRequest());
  75.         return $currentUser;
  76.     }
  77.     protected function checkLoginPasswordUpgraded(CurrentUser $currentUserRequest $request)
  78.     {
  79.         if (!$currentUser->isLogin()) {
  80.             return;
  81.         }
  82.         $user $this->getUserService()->getUser($currentUser->getId());
  83.         if (empty($user)) {
  84.             return;
  85.         }
  86.         if (== $user['passwordUpgraded']) {
  87.             return;
  88.         }
  89.         if (!= count($user['roles'])) {
  90.             $request->getSession()->set('needUpgradePassword'1);
  91.             return;
  92.         }
  93.         $loginBindSetting $this->getBiz()->service('System:SettingService')->get('login_bind');
  94.         if (!($loginBindSetting['login_strong_pwd_enable'] ?? 1)) {
  95.             return;
  96.         }
  97.         $request->getSession()->set('needUpgradePassword'1);
  98.     }
  99.     protected function authByToken(Request $request)
  100.     {
  101.         $authorization $request->headers->get('Authorization');
  102.         if (!empty($authorization) && (false !== strpos($authorization'Bearer '))) {
  103.             $token str_replace('Bearer '''$authorization);
  104.         } else {
  105.             $token $request->query->get('token');
  106.         }
  107.         if (empty($token)) {
  108.             return;
  109.         }
  110.         $storage $this->setting('storage', []);
  111.         try {
  112.             $payload JWT::decode($token, [$storage['cloud_access_key'] => $storage['cloud_secret_key']], ['HS256']);
  113.         } catch (\RuntimeException $e) {
  114.             return;
  115.         }
  116.         $user $this->getUserService()->getUser($payload->sub);
  117.         if (empty($user)) {
  118.             return;
  119.         }
  120.         $currentUser = new CurrentUser();
  121.         $currentUser->fromArray($user);
  122.         $biz $this->getBiz();
  123.         $biz['user'] = $currentUser;
  124.     }
  125.     protected function fillUserStatus($conditions)
  126.     {
  127.         if (isset($conditions['userStatus'])) {
  128.             if ('locked' == $conditions['userStatus']) {
  129.                 $conditions['locked'] = '1';
  130.             }
  131.             if ('unlock' == $conditions['userStatus']) {
  132.                 $conditions['locked'] = '0';
  133.             }
  134.             unset($conditions['userStatus']);
  135.             return $conditions;
  136.         }
  137.         return $conditions;
  138.     }
  139.     protected function fillOrgCode($conditions)
  140.     {
  141.         if ($this->setting('magic.enable_org')) {
  142.             if (!isset($conditions['orgCode'])) {
  143.                 $conditions['likeOrgCode'] = $this->getCurrentUser()->getSelectOrgCode();
  144.             } else {
  145.                 $conditions['likeOrgCode'] = $conditions['orgCode'];
  146.                 unset($conditions['orgCode']);
  147.             }
  148.         } else {
  149.             if (isset($conditions['orgCode'])) {
  150.                 unset($conditions['orgCode']);
  151.             }
  152.         }
  153.         return $conditions;
  154.     }
  155.     /**
  156.      * 判断是否微信内置浏览器访问.
  157.      *
  158.      * @return bool
  159.      */
  160.     protected function isWxClient()
  161.     {
  162.         return $this->isMobileClient() && false !== strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger');
  163.     }
  164.     /**
  165.      * 是否移动端访问访问.
  166.      *
  167.      * @return bool
  168.      */
  169.     protected function isMobileClient()
  170.     {
  171.         // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
  172.         if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
  173.             return true;
  174.         }
  175.         //如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
  176.         if (isset($_SERVER['HTTP_VIA'])) {
  177.             //找不到为flase,否则为true
  178.             return stristr($_SERVER['HTTP_VIA'], 'wap') ? true false;
  179.         }
  180.         //判断手机发送的客户端标志,兼容性有待提高
  181.         if (isset($_SERVER['HTTP_USER_AGENT'])) {
  182.             $clientkeywords = [
  183.                 'nokia''sony''ericsson''mot''samsung''htc''sgh''lg''sharp',
  184.                 'sie-''philips''panasonic''alcatel''lenovo''iphone''ipod''blackberry''meizu',
  185.                 'android''netfront''symbian''ucweb''windowsce''palm''operamini''operamobi',
  186.                 'openwave''nexusone''cldc''midp''wap''mobile',
  187.             ];
  188.             // 从HTTP_USER_AGENT中查找手机浏览器的关键字
  189.             if (preg_match('/('.implode('|'$clientkeywords).')/i'strtolower($_SERVER['HTTP_USER_AGENT']))) {
  190.                 return true;
  191.             }
  192.         }
  193.         //协议法,因为有可能不准确,放到最后判断
  194.         if (isset($_SERVER['HTTP_ACCEPT'])) {
  195.             // 如果只支持wml并且不支持html那一定是移动设备
  196.             // 如果支持wml和html但是wml在html之前则是移动设备
  197.             if ((false !== strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml'))
  198.                 && (false === strpos($_SERVER['HTTP_ACCEPT'], 'text/html')
  199.                     || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html'))
  200.                 )) {
  201.                 return true;
  202.             }
  203.         }
  204.         return false;
  205.     }
  206.     protected function purifyHtml($html$trusted false)
  207.     {
  208.         $biz $this->getBiz();
  209.         $htmlHelper $biz['html_helper'];
  210.         return $htmlHelper->purify($html$trusted);
  211.     }
  212.     protected function trans($id, array $parameters = [], $domain null$locale null)
  213.     {
  214.         return $this->container->get('translator')->trans($id$parameters$domain$locale);
  215.     }
  216.     protected function isPluginInstalled($pluginName)
  217.     {
  218.         return $this->get('kernel')->getPluginConfigurationManager()->isPluginInstalled($pluginName);
  219.     }
  220.     public function getPluginVersion($pluginName)
  221.     {
  222.         $plugins $this->get('kernel')->getPluginConfigurationManager()->getInstalledPlugins();
  223.         foreach ($plugins as $plugin) {
  224.             if (strtolower($plugin['code']) == strtolower($pluginName)) {
  225.                 return $plugin['version'];
  226.             }
  227.         }
  228.         return null;
  229.     }
  230.     protected function getTargetPath(Request $request)
  231.     {
  232.         if ($request->query->get('goto')) {
  233.             $targetPath $request->query->get('goto');
  234.         } elseif ($request->getSession()->has('_target_path')) {
  235.             $targetPath $request->getSession()->get('_target_path');
  236.         } else {
  237.             $targetPath $request->headers->get('Referer');
  238.         }
  239.         if (false !== strpos($targetPath'/register')) {
  240.             return $this->generateUrl('homepage');
  241.         }
  242.         if ($targetPath == $this->generateUrl('login', [], UrlGeneratorInterface::ABSOLUTE_URL)) {
  243.             return $this->generateUrl('homepage');
  244.         }
  245.         $url explode('?'$targetPath);
  246.         if ($url[0] == $this->generateUrl('partner_logout', [], UrlGeneratorInterface::ABSOLUTE_URL)) {
  247.             return $this->generateUrl('homepage');
  248.         }
  249.         if ($url[0] == $this->generateUrl('password_reset_update', [], UrlGeneratorInterface::ABSOLUTE_URL)) {
  250.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  251.         }
  252.         if (strpos($url[0], $request->getPathInfo()) > -1) {
  253.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  254.         }
  255.         if (false !== strpos($url[0], 'callback')
  256.             || false !== strpos($url[0], '/login/bind')
  257.             || false !== strpos($url[0], 'crontab')
  258.         ) {
  259.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  260.         }
  261.         if (empty($targetPath)) {
  262.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  263.         }
  264.         return $this->filterRedirectUrl($targetPath);
  265.     }
  266.     protected function setFlashMessage($level$message)
  267.     {
  268.         $this->get('session')->getFlashBag()->add($level$message);
  269.     }
  270.     protected function setFlashException(HttpExceptionInterface $exception)
  271.     {
  272.         $this->setFlashMessage(
  273.             'currentThrowedException',
  274.             [
  275.                 'code' => $exception->getCode(),
  276.                 'message' => $exception->getMessage(),
  277.                 'trace' => $exception->getTraceAsString(),
  278.                 'statusCode' => $exception->getStatusCode(),
  279.             ]
  280.         );
  281.     }
  282.     protected function agentInWhiteList($userAgent)
  283.     {
  284.         // com.tencent.mm.app.Application 是安卓端小程序在播放视频时的UA,无法找到为什么UA是这样的具体原因,为了容错
  285.         $whiteList = ['iPhone''iPad''Android''HTC''com.tencent.mm.app.Application'];
  286.         return ArrayToolkit::some($whiteList, function ($agent) use ($userAgent) {
  287.             return strpos($userAgent$agent) > -1;
  288.         });
  289.     }
  290.     protected function createNamedFormBuilder($name$data null, array $options = [])
  291.     {
  292.         return $this->container->get('form.factory')->createNamedBuilder($nameFormType::class, $data$options);
  293.     }
  294.     protected function createJsonResponse($data null$status 200$headers = [])
  295.     {
  296.         return new JsonResponse($data$status$headers);
  297.     }
  298.     protected function createJsonpResponse($data null$callback 'callback'$status 200$headers = [])
  299.     {
  300.         $response $this->createJsonResponse($data$status$headers);
  301.         return $response->setCallback($callback);
  302.     }
  303.     //@todo 此方法是为了和旧的调用兼容,考虑清理掉
  304.     protected function createErrorResponse($request$name$message)
  305.     {
  306.         $error = ['error' => ['name' => $name'message' => $message]];
  307.         return new JsonResponse($error'200');
  308.     }
  309.     /**
  310.      * JSONM
  311.      * https://github.com/lifesinger/lifesinger.github.com/issues/118.
  312.      */
  313.     protected function createJsonmResponse($data)
  314.     {
  315.         $response = new JsonResponse($data);
  316.         $response->setCallback('define');
  317.         return $response;
  318.     }
  319.     /**
  320.      * 创建消息提示响应.
  321.      *
  322.      * @param string $type     消息类型:info, warning, error
  323.      * @param string $message  消息内容
  324.      * @param string $title    消息抬头
  325.      * @param int    $duration 消息显示持续的时间
  326.      * @param string $goto     消息跳转的页面
  327.      *
  328.      * @return Response
  329.      */
  330.     protected function createMessageResponse($type$message$title ''$duration 0$goto null)
  331.     {
  332.         if (!in_array($type, ['info''warning''error'])) {
  333.             $this->createNewException(CommonException::ERROR_PARAMETER());
  334.         }
  335.         return $this->render('default/message.html.twig', [
  336.             'type' => $type,
  337.             'message' => $message,
  338.             'title' => $title,
  339.             'duration' => $duration,
  340.             'goto' => $this->filterRedirectUrl($goto),
  341.         ]);
  342.     }
  343.     protected function createResourceNotFoundException($resourceType$resourceId$message '')
  344.     {
  345.         return new ResourceNotFoundException($resourceType$resourceId$message);
  346.     }
  347.     public function createAccessDeniedException($message 'Access Denied', \Exception $previous null)
  348.     {
  349.         return new AccessDeniedException($message403$previous);
  350.     }
  351.     protected function createNewException($e)
  352.     {
  353.         if ($e instanceof AbstractException) {
  354.             throw $e;
  355.         }
  356.         throw new \Exception();
  357.     }
  358.     /**
  359.      * 安全的重定向.
  360.      *
  361.      * 如果url不属于非本站域名下的,则重定向到本周首页。
  362.      *
  363.      * @param $url string 重定向url
  364.      * @param $status int 重定向时的HTTP状态码
  365.      *
  366.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  367.      */
  368.     public function redirectSafely($url$status 302)
  369.     {
  370.         $url $this->filterRedirectUrl($url);
  371.         return $this->redirect($url$status);
  372.     }
  373.     public function render($view, array $parameters = [], Response $response null)
  374.     {
  375.         $biz $this->getBiz();
  376.         foreach ($biz['render_view_resolvers'] as $resolver) {
  377.             $view $resolver->generateRenderView($view$parameters);
  378.         }
  379.         return parent::render($view$parameters$response);
  380.     }
  381.     public function renderView($view, array $parameters = [])
  382.     {
  383.         $biz $this->getBiz();
  384.         foreach ($biz['render_view_resolvers'] as $resolver) {
  385.             $view $resolver->generateRenderView($view$parameters);
  386.         }
  387.         return parent::renderView($view$parameters);
  388.     }
  389.     /**
  390.      * 过滤URL.
  391.      *
  392.      * 如果url不属于非本站域名下的,则返回本站首页地址。
  393.      *
  394.      * @param $url string 待过滤的$url
  395.      *
  396.      * @return string
  397.      */
  398.     public function filterRedirectUrl($url)
  399.     {
  400.         $host $this->get('request_stack')->getCurrentRequest()->getHost();
  401.         $safeHosts = [$host];
  402.         $parsedUrl parse_url($url);
  403.         if (false == $parsedUrl) {
  404.             return $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  405.         }
  406.         if (!empty($parsedUrl['host'])) {
  407.             $url $this->unParseUrl($parsedUrl);
  408.         } elseif ('/' != $url[0]) {
  409.             $url $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  410.         }
  411.         $isUnsafeHost = isset($parsedUrl['host']) && !in_array($parsedUrl['host'], $safeHosts);
  412.         $isInvalidScheme = isset($parsedUrl['scheme']) && !in_array($parsedUrl['scheme'], ['http''https']);
  413.         if (empty($url) || $isUnsafeHost || $isInvalidScheme) {
  414.             $url $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  415.         }
  416.         return strip_tags($url);
  417.     }
  418.     protected function unParseUrl($parsedUrl)
  419.     {
  420.         $scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'].'://' '//';
  421.         $host $parsedUrl['host'] ?? '';
  422.         $port = isset($parsedUrl['port']) ? ':'.$parsedUrl['port'] : '';
  423.         $path $parsedUrl['path'] ?? '';
  424.         $query = isset($parsedUrl['query']) ? '?'.$parsedUrl['query'] : '';
  425.         $fragment = isset($parsedUrl['fragment']) ? '#'.$parsedUrl['fragment'] : '';
  426.         return "$scheme$host$port$path$query$fragment";
  427.     }
  428.     /**
  429.      * 验证验证码token
  430.      *
  431.      * @return [type] [description]
  432.      */
  433.     protected function checkDragCaptchaToken(Request $request$token)
  434.     {
  435.         $enableAntiBrushCaptcha $this->getBiz()->service('System:SettingService')->node('ugc_content_audit.enable_anti_brush_captcha');
  436.         if (empty($enableAntiBrushCaptcha)) {
  437.             return true;
  438.         }
  439.         $session $request->getSession();
  440.         $dragTokens = empty($session->get('dragTokens')) ? [] : $session->get('dragTokens');
  441.         if (in_array($token$dragTokens)) {
  442.             array_splice($dragTokensarray_search($token$dragTokens), 1);
  443.             $session->set('dragTokens'$dragTokens);
  444.             return true;
  445.         }
  446.         return false;
  447.     }
  448.     protected function createSuccessJsonResponse($data = [])
  449.     {
  450.         $data array_merge(['success' => 1], $data);
  451.         return $this->createJsonResponse($data);
  452.     }
  453.     protected function createFailJsonResponse($data = [])
  454.     {
  455.         $data array_merge(['success' => 0], $data);
  456.         return $this->createJsonResponse($data);
  457.     }
  458.     protected function getWebExtension()
  459.     {
  460.         return $this->get('web.twig.extension');
  461.     }
  462.     protected function createService($alias)
  463.     {
  464.         $biz $this->getBiz();
  465.         return $biz->service($alias);
  466.     }
  467.     protected function setting($name$default null)
  468.     {
  469.         return $this->get('web.twig.extension')->getSetting($name$default);
  470.     }
  471.     /**
  472.      * @return \Biz\User\Service\UserService
  473.      */
  474.     protected function getUserService()
  475.     {
  476.         return $this->getBiz()->service('User:UserService');
  477.     }
  478.     /**
  479.      * @return \Biz\System\Service\LogService
  480.      */
  481.     protected function getLogService()
  482.     {
  483.         return $this->getBiz()->service('System:LogService');
  484.     }
  485.     /**
  486.      * @return QiQiuYunSdkProxyService
  487.      */
  488.     protected function getQiQiuYunSdkProxyService()
  489.     {
  490.         return $this->createService('QiQiuYun:QiQiuYunSdkProxyService');
  491.     }
  492.     protected function pushEventTracking($action$data null)
  493.     {
  494.         return $this->getQiQiuYunSdkProxyService()->pushEventTracking($action$data);
  495.     }
  496.     protected function getJWTAuth()
  497.     {
  498.         $setting $this->setting('storage', []);
  499.         $accessKey = !empty($setting['cloud_access_key']) ? $setting['cloud_access_key'] : '';
  500.         $secretKey = !empty($setting['cloud_secret_key']) ? $setting['cloud_secret_key'] : '';
  501.         $key md5($accessKey.$secretKey);
  502.         return new JWTAuth($key);
  503.     }
  504.     protected function getHttpHost()
  505.     {
  506.         return $this->getSchema()."://{$_SERVER['HTTP_HOST']}";
  507.     }
  508.     protected function getSchema()
  509.     {
  510.         $https = empty($_SERVER['HTTPS']) ? '' $_SERVER['HTTPS'];
  511.         if (!empty($https) && 'off' !== strtolower($https)) {
  512.             return 'https';
  513.         }
  514.         return 'http';
  515.     }
  516. }