需求:前台登录和后台登录地址不同,都需要使用qq互联登录,且共用一套KEY,如何实现?经过两天的研究,发现qq互联回调地址可以填写多个,这样,原有的前台QQ互联登录无需修改,只需要添加一个回调地址,并用分号分割:
接下来,在配置文件,比如laravel .env文件中,添加一个回调地址QQ_REDIRECT_URI2:
//QQ登录配置 QQ_KEY= QQ_SECRET= QQ_REDIRECT_URI=https://blog.dzbfsj.com/qqlogin QQ_REDIRECT_URI2=https://blog.dzbfsj.com/admin/qqlogin
然后,在后台登录控制器中,以laravel-admin为例,AuthController.php文件添加一个方法,用于qq互联登录:
//QQ一键登录 public function qqlogin(Request $request) { header("Content-Type: text/html;charset=utf-8"); $app_id = env('QQ_KEY'); $app_secret = env('QQ_SECRET'); $my_url = env('QQ_REDIRECT_URI2'); //Step1:获取Authorization Code if (!isset($request->code)){ //state参数用于防止CSRF攻击,成功授权后回调时原样带回 $state = md5(uniqid(rand(), TRUE)); session(['state'=>$state]); $dialog_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=".$app_id."&redirect_uri=".urlencode($my_url)."&state=".$state; Header("Location: $dialog_url"); }elseif($request->state == session('state')) { //Step2:通过Authorization Code获取Access Token $token_url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&"."client_id=".$app_id."&redirect_uri=".urlencode($my_url)."&client_secret=".$app_secret."&code=".$request->code; $response = file_get_contents($token_url); //如果用户临时改变主意取消登录,返回true!==false,否则执行step3 if (strpos($response, "callback") !== false) { $lpos = strpos($response, "("); $rpos = strrpos($response, ")"); $response = substr($response, $lpos + 1, $rpos - $lpos -1); $msg = json_decode($response); if (isset($msg->error)) { echo "error:
".$msg->error; echo "msg :
".$msg->error_description; exit; } } $params = array(); parse_str($response, $params);//把传回来的数据参数变量化 //set access token to session $token = $params["access_token"]; $graph_url = "https://graph.qq.com/oauth2.0/me?access_token=$token"; $str = file_get_contents($graph_url); if (strpos($str, "callback") !== false) { $lpos = strpos($str, "("); $rpos = strrpos($str, ")"); $str = substr($str, $lpos + 1, $rpos - $lpos -1); } $user = json_decode($str); if (isset($user->error)) { echo "error:
" . $user->error; echo "msg :
" . $user->error_description; exit; } //debug //echo("Hello " . $user->openid); $openid = $user->openid; if($openid){ //查找数据库中是否有该openid $check = AdminUserModel::where('qqid', $openid)->first(); if (!$check) {//如果第一次访问,跳转到绑定账号页面 $bd = url("/admin/bdyyzh?timestamp=".time()."&qqid=".$openid); return redirect($bd); } else { //登录 $this->guard()->login($check); admin_toastr(trans('admin.login_successful')); $request->session()->regenerate(); return redirect()->intended($this->redirectPath()); } }else{ echo '没有获取到openid'; } }else{ echo "The state does not match. You may be a victim of CSRF."; } }
登录流程是,qq互联用户授权,获取到openid,数据库查询是否存在,不存在则跳转到绑定页面,存在则直接登录到后台。
本站使用了三个登录:微信、QQ、短信,因此在绑定账号时,也相应的进行绑定:
//绑定已有账号 public function bdyyzh(Request $request){ if(isset($request->qqid)){ $qqid = $request->qqid; return view('auth/adminbduser',compact('qqid')); }elseif(isset($request->openid)){ $openid = $request->openid; return view('auth/adminbduser',compact('openid')); }elseif(isset($request->phone)){ $phone = $request->phone; return view('auth/adminbduser',compact('phone')); } //session()->flash('success', 'QQ登录成功!'); //return redirect()->route('cxsy'); } //查询账号密码,如账号密码正确则更新qqid或openid或phone public function cxbd(Request $request){ //dd($request->all()); $this->loginValidator($request->all())->validate(); $credentials = $request->only([$this->username(), 'password']); $remember = $request->get('remember', false); if ($this->guard()->attempt($credentials, $remember)) { //验证通过 if(isset($request->qqid)){ $qqid = $request->qqid; AdminUserModel::where('username', $request->username)->update(['qqid' => $qqid]); }elseif(isset($request->openid)){ $openid = $request->openid; AdminUserModel::where('username', $request->username)->update(['openid' => $openid]); }elseif(isset($request->phone)){ $phone = $request->phone; AdminUserModel::where('username', $request->username)->update(['phone' => $phone]); } //保存session并跳转到后台 return $this->sendLoginResponse($request); }else{ session()->flash('danger', '很抱歉,您的用户名和密码不匹配!'); return redirect()->back()->withInput(); } }
如此,则实现了前台和后台共用一套key进行互联登录。