微信小程序微信登录

微信小程序 微信登录
参考:

使用微信登录

jwt

JWT 由头部(header)、载荷(payload)与签名(signature)组成.客户端请求的时候在 Header 中携带 Token,服务器获取 Token 后,进行 base64_decode 即可获取数据进行校验

token验证过程

DingoApi api.auth 中间件完成了token 验证。

  • 获取客户端提交的 token
  • 检测 token 中的签名 signature 是否正确
  • 判断 payload 数据中的 exp,是否已经过期
  • 根据 payload 数据中的 sub,取数据库中验证用户是否存在
    上述检测不正确,则抛出相应异常

安装jwt-auth

1
2
3
4
$ composer require tymon/jwt-auth:1.0.0-rc.4.1

//设置jwt的secret,用于最后的签名
$ php artisan jwt:secret

config/auth.php

1
2
3
4
5
6
7
8
9
10
11
12
13
...

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],

'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],

config/api.php

1
2
3
4
5
...

'auth' => [
'jwt' => 'Dingo\Api\Auth\Provider\JWT',
],

app/User.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
...

//返回user的id
public function getJWTIdentifier()
{
return $this->getKey();
}

//jwt payload 增加的自定义内容
public function getJWTCustomClaims()
{
return [];
}
}

进入 tinker

1
2
3
$user= App\User::first();
//生成access_token
Auth::guard('api')->fromUser($user);

修改数据表

1
$ php artisan make:migration add_weixin_session_key_to_users_table --table=users

database/migrations/<your_date>add_weixin_session_key_to_users_table.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddWeixinSessionKeyToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('weapp_openid')->nullable()->unique();
$table->string('weapp_session_key')->nullable()->after('weapp_openid');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('weapp_openid');
$table->dropColumn('weapp_session_key');
});
}
}
1
$ php artisan migrate

增加路由

routes/api.php

1
2
3
4
5
...

//微信登录
$api->post('weapp/authorizations','AuthorizationsController@weappStore')
->name('api.weapp.authorizations.store');

增加Request

1
$ php artisan make:request Api/WeappAuthorizationRequest

app/Http/Requests/Api/WeappAuthorizationRequest.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

namespace App\Http\Requests\Api;

class WeappAuthorizationRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'code' => 'required|string',
];
}
}

修改Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php

namespace App\Http\Controllers\Api;

use App\Http\Requests\Api\WeappAuthorizationRequest;
use App\User;
use Auth;
class AuthorizationsController extends Controller
{
public function weappStore(WeappAuthorizationRequest $request)
{
$code = $request->code;

$miniProgram = \EasyWeChat::miniProgram();
$data = $miniProgram->auth->session($code);


if (isset($data['errcode'])) {
return $this->response->errorUnauthorized('code不正确');
}

//根据weapp_openid查找用户
$user = User::where('weapp_openid',$data['openid'])->first();

$attributes['weapp_session_key'] = $data['session_key'];

if (!$user) {
if (!$request->username) {
//403 status code
return $this->response->errorForbidden('用户不存在');
}

$username = $request->username;

filter_var($username,FILTER_VALIDATE_EMAIL) ?
$credentials['email'] = $username :
$credentials['phone'] = $username;

$credentials['password'] = $request->password;

//验证登录的用户是否存在
if (!Auth::guard('api')->attempt($credentials)) {
return $this->response->errorUnauthorized('用户名和密码不正确');
}

$user = Auth::guard('api')->getUser();
$attributes['weapp_openid'] = $data['openid'];

}

//更新用户的weapp_openid,weapp_session_key
$user->update($attributes);

$token = Auth::guard('api')->fromUser($user);

return $this->respondWithToken($token);
}

protected function respondWithToken($token)
{
return $this->response->array([
'access_token' => $token,
'token_type' => 'Bearer',
'expires_in' => \Auth::guard('api')->factory()->getTTL() * 60
]);
}
}
  • 提交 code,验证 code 的正确性
  • 通过 openid 查找用户,用户不存在,且用户未提交用户名,返回403
  • 用户不存在 ,用户名提交用户名和密码,验证用户和密码是否正确,错误返回401
  • 未绑定微信的用户更新 openid,session_key;绑定的用户只更新 session_key.
  • 最后返回 access_token

app/User.php

1
2
3
4
...
protected $fillable = [
'name', 'email', 'password','phone','weapp_openid','weapp_session_key',
];

Postman测试

code只能使用一次,每次测试要刷新微信小程序端的code

code验证通过,没有提交用户名


用户名和密码验证用过,没有和微信绑定的情况


用户和微信绑定的情况