|
@@ -0,0 +1,348 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Http\Middleware;
|
|
|
+
|
|
|
+use Closure;
|
|
|
+use Encore\Admin\Facades\Admin;
|
|
|
+use Illuminate\Log\Logger;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
+use Illuminate\Support\Facades\Redis;
|
|
|
+use Illuminate\Support\Facades\Validator;
|
|
|
+use Monolog\Handler\RotatingFileHandler;
|
|
|
+
|
|
|
+//站点用户验证
|
|
|
+
|
|
|
+class PsyUserSso
|
|
|
+{
|
|
|
+ const USER_DATA_URL = "/api.php";
|
|
|
+ private $url = "/admin/ssoIndex";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Handle an incoming request.
|
|
|
+ *
|
|
|
+ * @param \Illuminate\Http\Request $request
|
|
|
+ * @param \Closure $next
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function handle($request, Closure $next)
|
|
|
+ {
|
|
|
+ if (Admin::guard()->check()){
|
|
|
+ return $next($request);
|
|
|
+ }
|
|
|
+ $sign = $request->get("sign");
|
|
|
+ $signData = $request->only(array("task","appid","open_id","version","go_url"));
|
|
|
+ $config = config("console.remote_sso");
|
|
|
+ if ($config["appid"] != $signData["appid"]){
|
|
|
+ throw new \Exception("appid非法参数:{$signData["appid"]}");
|
|
|
+ }
|
|
|
+ $paramsData = $request->except(array("appid","op", "task","version","sign","go_url"));
|
|
|
+ $userModelClass = config('admin.database.users_model');
|
|
|
+
|
|
|
+ $userModel = new $userModelClass();
|
|
|
+
|
|
|
+ if (Admin::guard()->check() && Admin::user()->third_openid == $signData["open_id"]){
|
|
|
+ //更新用户信息
|
|
|
+
|
|
|
+ $res = DB::table($userModel::query()->getModel()->getTable())->where(
|
|
|
+ array("id"=>Admin::user()->id)
|
|
|
+ )->update(array(
|
|
|
+ "third_openid"=>$signData["open_id"],
|
|
|
+ "workstation_id"=>$paramsData['outside_c_id'],
|
|
|
+ "workstation_name"=>$paramsData['visit_title']
|
|
|
+ ));
|
|
|
+ return $next($request);
|
|
|
+ }
|
|
|
+
|
|
|
+ $userData = $this->getUserData($signData["open_id"]);//下面需要获取用户账号、昵称、头像
|
|
|
+ // $nowSign=$this->getSign(
|
|
|
+ // $paramsData,
|
|
|
+ // "core",
|
|
|
+ // $signData["task"],
|
|
|
+ // $signData["version"]
|
|
|
+ // );
|
|
|
+ // if ($nowSign != $sign){
|
|
|
+ // throw new \Exception("签名验证不能通过:sign:{$sign}、nowSign:{$nowSign}");
|
|
|
+ // }
|
|
|
+ $checkUserData = $userModel::query()
|
|
|
+ ->where(
|
|
|
+ array(
|
|
|
+ "third_openid"=>$signData["open_id"],
|
|
|
+ )
|
|
|
+ )
|
|
|
+ ->orderBy("id","desc")->first();
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+ $plaintext = "";
|
|
|
+ $defaultPassword = "";
|
|
|
+ if (!empty($checkUserData)){
|
|
|
+ $plaintext = "{$checkUserData->username}@123456";
|
|
|
+ $defaultPassword = bcrypt($plaintext);
|
|
|
+ }
|
|
|
+ if (empty($checkUserData)){
|
|
|
+ //开始菜单授权
|
|
|
+ $permissionModelClass = config('admin.database.permissions_model');
|
|
|
+ $roleModelClass = config('admin.database.roles_model');
|
|
|
+ $userAvatar = config('admin.default_avatar');
|
|
|
+ $name = "";//名称
|
|
|
+ $userName="";//登录账号
|
|
|
+ $userData = $this->getUserData($signData["open_id"]);//下面需要获取用户账号、昵称、头像
|
|
|
+ if (isset($userData["user"])){
|
|
|
+ if (isset($userData["user"]["name"])){
|
|
|
+ $name = $userData["user"]["name"];
|
|
|
+ }
|
|
|
+ $name = empty($name)?$userData["user"]["username"]:$name;
|
|
|
+ $userName = $userData["user"]["username"];
|
|
|
+ }
|
|
|
+ $plaintext = "{$userName}@123456";
|
|
|
+ $defaultPassword = bcrypt($plaintext);
|
|
|
+ $checkUserData = $userModel->create(array(
|
|
|
+ "username"=>$userName,
|
|
|
+ "password"=>$defaultPassword,
|
|
|
+ "name"=>$name,
|
|
|
+ "avatar"=>null,
|
|
|
+ ));
|
|
|
+ if (empty($checkUserData)){
|
|
|
+ throw new \RuntimeException("新增用户信息失败");
|
|
|
+ }
|
|
|
+ DB::table($userModel::query()->getModel()->getTable())->where(
|
|
|
+ array("id"=>$checkUserData->id)
|
|
|
+ )->update(array(
|
|
|
+ "third_openid"=>$signData["open_id"],
|
|
|
+ "workstation_id"=>$paramsData['outside_c_id'],
|
|
|
+ "workstation_name"=>$paramsData['visit_title']
|
|
|
+ ));
|
|
|
+ $roleSlugName = array("RemoteSso");//角色名称 slug
|
|
|
+ $permissionsSlugName = array("RemoteSso");//权限名称 slug
|
|
|
+ $permissionModel = new $permissionModelClass();
|
|
|
+ $roleModel = new $roleModelClass();
|
|
|
+ foreach ($roleSlugName as $val){
|
|
|
+ $roleData = $roleModel::query()
|
|
|
+ ->where(
|
|
|
+ array(
|
|
|
+ "slug"=>$val
|
|
|
+ )
|
|
|
+ )
|
|
|
+ ->orderBy("id","desc")->first();
|
|
|
+ if (!empty($roleData)){
|
|
|
+ DB::table("admin_role_users")->insert(
|
|
|
+ array(
|
|
|
+ "role_id"=>$roleData->id,
|
|
|
+ "user_id"=>$checkUserData->id,
|
|
|
+ "created_at"=>date("Y-m-d H:i:s")
|
|
|
+ )
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ foreach ($permissionsSlugName as $val){
|
|
|
+ $permissionData = $permissionModel::query()
|
|
|
+ ->where(
|
|
|
+ array(
|
|
|
+ "slug"=>$val
|
|
|
+ )
|
|
|
+ )
|
|
|
+ ->orderBy("id","desc")->first();
|
|
|
+ if (!empty($permissionData)){
|
|
|
+ DB::table("admin_user_permissions")->insert(
|
|
|
+ array(
|
|
|
+ "permission_id"=>$permissionData->id,
|
|
|
+ "user_id"=>$checkUserData->id,
|
|
|
+ "created_at"=>date("Y-m-d H:i:s")
|
|
|
+ )
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ DB::commit();
|
|
|
+
|
|
|
+ Admin::guard()->login(
|
|
|
+ $checkUserData
|
|
|
+ );
|
|
|
+ auth('admin')->login(
|
|
|
+ $checkUserData
|
|
|
+ );
|
|
|
+ // echo 'aaaaaaa';exit;
|
|
|
+
|
|
|
+ $key = "RemoteSso:".$_SERVER['HTTP_HOST'].":".$checkUserData->id;
|
|
|
+ Redis::SET($key, true);
|
|
|
+ $goUrl = $signData['go_url'] ?: $this->url;
|
|
|
+
|
|
|
+ // Log::info("登录成功",[$checkUserData->id,$checkUserData->username, $goUrl]);
|
|
|
+ return $next($request);
|
|
|
+
|
|
|
+ }catch (\Exception $exception){
|
|
|
+ // Log::error("远程授权登录出错",[$exception->getMessage(),$exception->getTrace()]);
|
|
|
+ DB::rollBack();
|
|
|
+ return "登录失败";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public function getUserData(string $openId)
|
|
|
+ {
|
|
|
+ if (empty($openId)){
|
|
|
+ throw new \Exception("openId不能为空");
|
|
|
+ }
|
|
|
+ $config = config("console.remote_sso");
|
|
|
+ $url = $config["url"].self::USER_DATA_URL;//http://www.baidu.com/api.php
|
|
|
+ $query = array(
|
|
|
+ "op"=>"user",
|
|
|
+ "task"=>"userData",
|
|
|
+ "version"=>"1.0.0",
|
|
|
+ "appid"=>$config["appid"]
|
|
|
+ );
|
|
|
+ $sendData = array(
|
|
|
+ "open_id"=>$openId
|
|
|
+ );
|
|
|
+ $postData = $sendData;
|
|
|
+ $query["sign"] = $this->getSign($postData,$query["op"],$query["task"],$query["version"]);
|
|
|
+// $client = new Client();
|
|
|
+ $url = $url."?".http_build_query($query);
|
|
|
+ $resultStr = $this->curlPost($url,$postData);
|
|
|
+// $response = $client->request('post', $url, [
|
|
|
+// 'query' => $query,
|
|
|
+// "headers"=>array(
|
|
|
+// "Content-type"=>"application/json"
|
|
|
+// ),
|
|
|
+// "form_params"=>$postData
|
|
|
+// ]);
|
|
|
+// $resultStr = $response->getBody()->getContents();
|
|
|
+ return $this->getResult($resultStr);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getSign(array $sendData, string $op = "user", string $task = "login", string $version = "1.0.0")
|
|
|
+ {
|
|
|
+ $config = config("console.remote_sso");
|
|
|
+ $appid = $config["appid"];
|
|
|
+ $secret = $config["secret"];
|
|
|
+ ksort($sendData);
|
|
|
+ $str = "";
|
|
|
+ foreach($sendData as $key =>$value){
|
|
|
+ $str.= stripslashes($value);
|
|
|
+ }
|
|
|
+ $sign = md5($appid. $op . $task . $version . $str. $secret);
|
|
|
+ return $sign;
|
|
|
+ }
|
|
|
+ public function getSsoSign(array $data)
|
|
|
+ {
|
|
|
+ $config = config("console.remote_sso");
|
|
|
+ $appid = $config["appid"];
|
|
|
+ $secret = $config["secret"];
|
|
|
+ ksort($sendData);
|
|
|
+ $str = "";
|
|
|
+ foreach($sendData as $key =>$value){
|
|
|
+ $str.= stripslashes($value);
|
|
|
+ }
|
|
|
+ $sign = md5($appid. $str. $secret);
|
|
|
+ return $sign;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 得到结果数据
|
|
|
+ * @param string $resultStr
|
|
|
+ * @return mixed
|
|
|
+ * @throws \Exception
|
|
|
+ */
|
|
|
+ private function getResult(string $resultStr){
|
|
|
+ $result = json_decode($resultStr,true);
|
|
|
+ if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
+ // $this->log("数据格式响应错误",$resultStr);
|
|
|
+ throw new \Exception("数据格式响应错误".$resultStr);
|
|
|
+ }
|
|
|
+ if (empty($result["status"])){
|
|
|
+ $content = $result["message"] ?? $resultStr;
|
|
|
+ // $this->log("结果信息发生错误",$content);
|
|
|
+ throw new \Exception("结果信息发生错误".$content);
|
|
|
+ }
|
|
|
+ if (!isset($result["data"])){
|
|
|
+ $content = $resultStr;
|
|
|
+ // $this->log("结果信息格式发送错误",$content);
|
|
|
+ throw new \Exception("结果信息格式发送错误".$content);
|
|
|
+ }
|
|
|
+ return $result["data"];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function curlPost($url, $data=null, $file=null)
|
|
|
+ {
|
|
|
+ $ch = curl_init($url);
|
|
|
+ curl_setopt($ch, CURLOPT_TIMEOUT, 60); //设置超时
|
|
|
+
|
|
|
+// if(!empty($file)){
|
|
|
+// foreach ($file as $k=>$v){
|
|
|
+// if(is_array($v)){
|
|
|
+// //多个文件
|
|
|
+// foreach ($v as $key=>$val){
|
|
|
+// $data[$k.'['.$key.']'] = new CURLFile($val);
|
|
|
+// }
|
|
|
+// }else{
|
|
|
+// //一维
|
|
|
+// $data[$k] = new CURLFile($v);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+ if (0 === strpos(strtolower($url), "https")) {
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //对认证证书来源的检查
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //从证书中检查SSL加密算法是否存在
|
|
|
+ }
|
|
|
+ curl_setopt($ch, CURLOPT_POST, true);
|
|
|
+
|
|
|
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
|
|
+
|
|
|
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
+
|
|
|
+// curl_setopt($ch, CURLOPT_HTTPHEADER);
|
|
|
+ $rtn = curl_exec($ch);//CURLOPT_RETURNTRANSFER 不设置 curl_exec返回TRUE 设置 curl_exec返回json(此处) 失败都返回FALSE
|
|
|
+ curl_close($ch);
|
|
|
+ return $rtn;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * json 形式传参
|
|
|
+ * @param unknown $url
|
|
|
+ * @param unknown $data
|
|
|
+ */
|
|
|
+ private function curlPostJson($url, $data = null)
|
|
|
+ {
|
|
|
+ $headers = array(
|
|
|
+ "Content-type: application/json;charset='utf-8'",
|
|
|
+ "Accept: application/json",
|
|
|
+ "Cache-Control: no-cache",
|
|
|
+ "Pragma: no-cache",
|
|
|
+ );
|
|
|
+ $ch = curl_init($url);
|
|
|
+ curl_setopt($ch, CURLOPT_TIMEOUT, 60); //设置超时
|
|
|
+
|
|
|
+ if (0 === strpos(strtolower($url), "https")) {
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //对认证证书来源的检查
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //从证书中检查SSL加密算法是否存在
|
|
|
+ }
|
|
|
+ curl_setopt($ch, CURLOPT_POST, true);
|
|
|
+
|
|
|
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
|
|
+
|
|
|
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
|
|
+ curl_setopt($ch, CURLOPT_HEADER, 1);//打印响应header
|
|
|
+ $rtn = curl_exec($ch);//CURLOPT_RETURNTRANSFER 不设置 curl_exec返回TRUE 设置 curl_exec返回json(此处) 失败都返回FALSE
|
|
|
+
|
|
|
+ $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
|
|
+
|
|
|
+ // 根据头大小去获取头信息内容
|
|
|
+ $header = substr($rtn, 0, $header_size);
|
|
|
+
|
|
|
+ $data = substr($rtn, $header_size);
|
|
|
+
|
|
|
+ $is_gzipped = false;
|
|
|
+
|
|
|
+ if (preg_match("/Content-Encoding: gzip/", $header)) {
|
|
|
+ $is_gzipped = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if($is_gzipped){
|
|
|
+ $data = gzdecode($data);
|
|
|
+ }
|
|
|
+
|
|
|
+ curl_close($ch);
|
|
|
+
|
|
|
+ return $data;
|
|
|
+ }
|
|
|
+}
|