PsyUserVerify.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. namespace App\Http\Middleware;
  3. use Closure;
  4. use Encore\Admin\Facades\Admin;
  5. use Illuminate\Log\Logger;
  6. use Illuminate\Support\Facades\DB;
  7. use Illuminate\Support\Facades\Log;
  8. use Illuminate\Support\Facades\Redis;
  9. use Illuminate\Support\Facades\Validator;
  10. use Monolog\Handler\RotatingFileHandler;
  11. //社心站点用户验证
  12. class PsyUserVerify
  13. {
  14. const USER_DATA_URL = "/api.php";
  15. /**
  16. * Handle an incoming request.
  17. *
  18. * @param \Illuminate\Http\Request $request
  19. * @param \Closure $next
  20. * @return mixed
  21. */
  22. public function handle($request, Closure $next)
  23. {
  24. $validator = Validator::make($request->all(), [
  25. 'appid' => 'required',
  26. 'open_id' => 'required',
  27. 'op' => 'required',
  28. 'task' => 'required',
  29. ], [
  30. 'appid.required' => 'appid参数不能为空',
  31. 'open_id.required' => 'open_id参数不能为空',
  32. 'op.required' => 'op参数不能为空',
  33. 'task.required' => 'task参数不能为空',
  34. ]);
  35. if ($validator->fails()) {
  36. $msg = $validator->errors()->first();
  37. return response()->json([
  38. 'code'=>400,
  39. 'msg'=>$msg
  40. ]);
  41. }
  42. $sign = $request->input("sign");
  43. $signData = $request->only(array("appid","open_id","op", "task","version"));
  44. $paramsData = $request->except(array("appid","op", "task","version","sign"));
  45. $config = config("console.wg_map");
  46. if ($config["appid"] != $signData["appid"]){
  47. throw new \Exception("appid非法参数:{$signData["appid"]}");
  48. }
  49. if (Admin::guard()->check() && Admin::user()->third_openid == $signData["open_id"]){
  50. return next($request);
  51. }
  52. $nowSign=$this->getSign(
  53. $paramsData,
  54. $signData["op"],
  55. $signData["task"],
  56. $signData["version"]
  57. );
  58. if ($nowSign != $sign){
  59. throw new \Exception("签名验证不能通过:sign:{$sign}、nowSign:{$nowSign}");
  60. }
  61. $userModelClass = config('admin.database.users_model');
  62. $userModel = new $userModelClass();
  63. $checkUserData = $userModel::query()
  64. ->where(
  65. array(
  66. "third_openid"=>$signData["open_id"]
  67. )
  68. )
  69. ->orderBy("id","desc")->first();
  70. if($checkUserData) {
  71. Admin::guard()->login(
  72. $checkUserData
  73. );
  74. }
  75. return $next($request);
  76. }
  77. public function getUserData(string $openId)
  78. {
  79. if (empty($openId)){
  80. throw new \Exception("openId不能为空");
  81. }
  82. $config = config("console.remote_sso");
  83. $url = $config["url"].self::USER_DATA_URL;//http://www.baidu.com/api.php
  84. $query = array(
  85. "op"=>"user",
  86. "task"=>"userData",
  87. "version"=>"1.0.0",
  88. "appid"=>$config["appid"]
  89. );
  90. $sendData = array(
  91. "open_id"=>$openId
  92. );
  93. $postData = $sendData;
  94. $query["sign"] = $this->getSign($postData,$query["op"],$query["task"],$query["version"]);
  95. // $client = new Client();
  96. $url = $url."?".http_build_query($query);
  97. $resultStr = $this->curlPost($url,$postData);
  98. // $response = $client->request('post', $url, [
  99. // 'query' => $query,
  100. // "headers"=>array(
  101. // "Content-type"=>"application/json"
  102. // ),
  103. // "form_params"=>$postData
  104. // ]);
  105. // $resultStr = $response->getBody()->getContents();
  106. return $this->getResult($resultStr);
  107. }
  108. public function getUserMenuWebsiteData(string $openId)
  109. {$config = config("console.remote_sso");
  110. $url = $config["url"].self::USER_DATA_URL;//http://www.baidu.com/api.php
  111. $query = array(
  112. "op"=>"menu",
  113. "task"=>"getMenu",
  114. "version"=>"1.0.0",
  115. "appid"=>$config["appid"]
  116. );
  117. $sendData = array(
  118. "open_id"=>$openId
  119. );
  120. $query["sign"] = $this->getSign($sendData,$query["op"],$query["task"],$query["version"]);
  121. // $client = new Client();
  122. // $response = $client->request('post', $url, [
  123. // 'query' => $query,
  124. // "headers"=>array(
  125. // "Content-type"=>"application/json"
  126. // ),
  127. // "form_params"=>$sendData
  128. // ]);
  129. // $resultStr = $response->getBody()->getContents();
  130. $url = $url."?".http_build_query($query);
  131. $resultStr = $this->curlPost($url,$sendData);
  132. return $this->getResult($resultStr);
  133. }
  134. public function getSign(array $sendData, string $op = "user", string $task = "login", string $version = "1.0.0")
  135. {
  136. $config = config("console.wg_map");
  137. $appid = $config["appid"];
  138. $secret = $config["secret"];
  139. ksort($sendData);
  140. $str = "";
  141. foreach($sendData as $key =>$value){
  142. $str.= stripslashes($value);
  143. }
  144. $sign = md5($appid. $op . $task . $version . $str. $secret);
  145. return $sign;
  146. }
  147. /**
  148. * 得到结果数据
  149. * @param string $resultStr
  150. * @return mixed
  151. * @throws \Exception
  152. */
  153. private function getResult(string $resultStr){
  154. $result = json_decode($resultStr,true);
  155. if (json_last_error() !== JSON_ERROR_NONE) {
  156. $this->log("数据格式响应错误",$resultStr);
  157. throw new \Exception("数据格式响应错误".$resultStr);
  158. }
  159. if (empty($result["status"])){
  160. $content = $result["message"] ?? $resultStr;
  161. $this->log("结果信息发生错误",$content);
  162. throw new \Exception("结果信息发生错误".$content);
  163. }
  164. if (!isset($result["data"])){
  165. $content = $resultStr;
  166. $this->log("结果信息格式发送错误",$content);
  167. throw new \Exception("结果信息格式发送错误".$content);
  168. }
  169. return $result["data"];
  170. }
  171. /**
  172. * @param string $msg 消息提示
  173. * @param array|string|object $content 结果内容
  174. * @return void
  175. */
  176. private function log(string $msg,$content)
  177. {
  178. $sqlFile = 'logs/remoteSso/info.log';
  179. (new Logger('remoteSso'))->pushHandler(new RotatingFileHandler(storage_path($sqlFile)))->info($msg,[$content]);
  180. }
  181. private function curlPost($url, $data=null, $file=null)
  182. {
  183. $ch = curl_init($url);
  184. curl_setopt($ch, CURLOPT_TIMEOUT, 60); //设置超时
  185. // if(!empty($file)){
  186. // foreach ($file as $k=>$v){
  187. // if(is_array($v)){
  188. // //多个文件
  189. // foreach ($v as $key=>$val){
  190. // $data[$k.'['.$key.']'] = new CURLFile($val);
  191. // }
  192. // }else{
  193. // //一维
  194. // $data[$k] = new CURLFile($v);
  195. // }
  196. // }
  197. // }
  198. if (0 === strpos(strtolower($url), "https")) {
  199. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //对认证证书来源的检查
  200. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //从证书中检查SSL加密算法是否存在
  201. }
  202. curl_setopt($ch, CURLOPT_POST, true);
  203. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  204. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  205. // curl_setopt($ch, CURLOPT_HTTPHEADER);
  206. $rtn = curl_exec($ch);//CURLOPT_RETURNTRANSFER 不设置 curl_exec返回TRUE 设置 curl_exec返回json(此处) 失败都返回FALSE
  207. curl_close($ch);
  208. return $rtn;
  209. }
  210. /**
  211. * json 形式传参
  212. * @param unknown $url
  213. * @param unknown $data
  214. */
  215. private function curlPostJson($url, $data = null)
  216. {
  217. $headers = array(
  218. "Content-type: application/json;charset='utf-8'",
  219. "Accept: application/json",
  220. "Cache-Control: no-cache",
  221. "Pragma: no-cache",
  222. );
  223. $ch = curl_init($url);
  224. curl_setopt($ch, CURLOPT_TIMEOUT, 60); //设置超时
  225. if (0 === strpos(strtolower($url), "https")) {
  226. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //对认证证书来源的检查
  227. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //从证书中检查SSL加密算法是否存在
  228. }
  229. curl_setopt($ch, CURLOPT_POST, true);
  230. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  231. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  232. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  233. curl_setopt($ch, CURLOPT_HEADER, 1);//打印响应header
  234. $rtn = curl_exec($ch);//CURLOPT_RETURNTRANSFER 不设置 curl_exec返回TRUE 设置 curl_exec返回json(此处) 失败都返回FALSE
  235. $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  236. // 根据头大小去获取头信息内容
  237. $header = substr($rtn, 0, $header_size);
  238. $data = substr($rtn, $header_size);
  239. $is_gzipped = false;
  240. if (preg_match("/Content-Encoding: gzip/", $header)) {
  241. $is_gzipped = true;
  242. }
  243. if($is_gzipped){
  244. $data = gzdecode($data);
  245. }
  246. curl_close($ch);
  247. return $data;
  248. }
  249. }