laravel实现微信公众号授权登录实战
微信公众号授权登录实战
框架:laravel
依赖:overtrue/wechat
首先安装一下easywechat依赖
composer require overtrue/wechat:~4.0 -vvv
安装完成后我们定义一个makeWechat方法
public static function makeWechat()
{
$config = [
'app_id' => env('WECHAT_APPID'),
'secret' => env('WECHAT_APPSECRET'),
'response_type' => 'array',
];
$app = Factory::officialAccount($config);
return $app;
}
我们return的$app后面要用到的地方很多,所以直接定义一个基础方法吧
写一个中间件,该中间件管理所有需要登录才能操作的接口
<?php
namespace App\Http\Middleware;
use App\Libraries\AdminSend;
use App\Model\UserModel;
use Closure;
class CheckLogin
{
use AdminSend;
public function handle($request, Closure $next)
{
$url = $request->fullUrl();
try {
$key = env("TOKEN_KEY");
$header = $request->cookie('authorization');
$authorizationInfo =
explode(":", openssl_decrypt(base64_decode($header), 'DES-EDE3', $key, OPENSSL_RAW_DATA));
if (!is_array($authorizationInfo) || $authorizationInfo[0] < 1)
return self::returnLogin($url);
$user = UserModel::get_by_id((int)$authorizationInfo[0]);
if ($user and !isset($user) || $user['token'] != $authorizationInfo[1])
return self::returnLogin($url);
$request->attributes->add(['uid' => $authorizationInfo[0], 'user' => $user]);
return $next($request);
} catch (\Exception $e) {
return self::returnLogin($url);
}
}
}
主要逻辑是取request的cookie值,通过cookie值来判断用户是否登录了。
如果没有登录就returnLogin,该方法有一个参数为url,目的是为了跳转到微信公众号登录且登录成功后还继续跳回到之前用户想要访问的页面
看看returnLogin方法
public static function returnLogin($url)
{
Session::flash("redirect_url", $url);
$app = self::makeWechat();
$oauth = $app->oauth;
return $oauth->scopes(['snsapi_userinfo'])->redirect(url("/user/login"));
}
首先用了一个Session::falsh方法,这里就是通过seesion来缓存当前用户的来源地址,也就是为了上面提到了登录成功后继续跳转到登录之前的来路页面
然后跳转到user/login方法
来看看我们的login方法
public function login(Request $request)
{
$app = self::makeWechat();
$oauth = $app->oauth;
$user_wechat = $oauth->user()->toArray();
$user = UserModel::query()->where('openid', $user_wechat['id'])->first();
if (!isset($user)) {
$user = new UserModel();
$user->name = $user_wechat['name'];
$user->openid = $user_wechat['id'];
$user->token = $user_wechat['token'];
$user->avatar = $user_wechat['avatar'];
$user->sex = $user_wechat['original']['sex'];
$user->provider = "wechat";
$user->create_time = time();
$user->save();
}
$token = self::TokenEncrypt($user['id'], $user['token'], env("TOKEN_KEY"));
$url = Session::get("redirect_url");
return response()->redirectTo($url)->withCookie(cookie('authorization', $token));
}
用户通过微信公众号授权后就会访问该方法,该方法拿到用户的openid去比对我们的数据库是否存在会员,如果存在就是登录,如果不存在那么就需要为该用户注册账号。
登录成功后返回登录cookie并且跳转到来路页面。
这里有一个TokenEncrypt的方法,其实就是生成我们的cookie一并分享出来吧
public function TokenEncrypt(int $uid, $token, $key = "UF((&)(&^#&)@!")
{
$encryptToken = base64_encode(openssl_encrypt("{$uid}:{$token}", 'DES-EDE3', $key, OPENSSL_RAW_DATA));
return $encryptToken;
}
还有我们的数据库user表的结构
# Host: blog.95shouyou.com (Version: 5.7.32-log) # Date: 2020-12-31 14:04:11 # Generator: MySQL-Front 5.3 (Build 4.234) /*!40101 SET NAMES utf8 */; # # Structure for table "user" # CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '' COMMENT '用户昵称', `token` varchar(128) NOT NULL DEFAULT '' COMMENT '微信token', `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', `pid` int(11) NOT NULL DEFAULT '0' COMMENT '邀请人', `openid` varchar(255) NOT NULL DEFAULT '' COMMENT '微信openid', `avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '用户头像', `sex` tinyint(3) NOT NULL DEFAULT '0' COMMENT '性别', `provider` char(32) NOT NULL DEFAULT '' COMMENT '用户渠道', PRIMARY KEY (`id`), KEY `openid` (`openid`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='用户';
