一、下载官方sdk
composer require alibabacloud/sdk
二、创建短信配置文件
config/sms.php
<?php
/**
* 短信相关配置
*/
return [
// 阿里云秘钥ID
'access_key_id' => '',
// 阿里云秘钥secret
'access_secret' => '',
// 短信模板签名
'sign_name' => '',
// 短信模板代码
'template_code' => ''
];
三、创建路由与控制器
1. 路由
Route ::match(['post', 'get'], 'mobile_login', [App\Http\Controllers\Auth\MobileController::class, 'login'])->name('app.oauth.mobile_login');
Route ::post('auth/mobile_code', [App\Http\Controllers\Auth\MobileController::class, 'getMobileCode'])->name('app.oauth.mobile_code');
2. 控制器
Auth/MobileController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\Models\User;
use Cache;
class MobileController extends Controller
{
public function __construct()
{
$this->middleware('guest');
}
public function login(Request $request)
{
if($request->isMethod('POST')){
if(Cache::has('mobile_code_'.$request->mobile)){
if($request->code == json_decode(Cache::get('mobile_code_'.$request->mobile))->code){
// 注册或登录
$user = User::where(['mobile'=>$request->mobile])->first();
if($user){
Auth::login($user);
}else{
$new_user = User::create([
'name' => 'u_'.$request->code,
'email' => 'u_'.$request->code.'@email.com',
'mobile' => $request->mobile,
'password' => Hash::make($request->code.time()),
]);
Auth::login($new_user);
}
return redirect()->route('index')->with(['msg'=>__('登录成功'), 'alert'=>'success']);
}else{
return redirect()->back()->with(['msg'=>__('验证码错误1'), 'alert'=>'error']);
}
}else{
return redirect()->back()->with(['msg'=>__('验证码错误1'), 'alert'=>'error']);
}
}else{
return view('auth.mobile_login');
}
}
// 获取短信
public function getMobileCode(Request $request)
{
$mobile = $request->get('mobile');
if(!$mobile){
return ['status'=>'error', 'message'=>__('手机号码格式不正确')];
}
$authCode = json_encode(['code'=>mt_rand(100000,999999), 'dateline'=>time()]);
$successCode = $this->sendMobileCode($mobile, $authCode);
if($successCode){
Cache::put('mobile_code_'.$mobile, $authCode, 180);
return ['status'=>'success', 'message'=>__('发送成功,请注意查收,3分钟内有效')];
}else{
return ['status'=>'error', 'message'=>__('发送失败')];
}
}
public function sendMobileCode($mobile, $authCode)
{
AlibabaCloud::accessKeyClient(config('sms.access_key_id'),config('sms.access_secret'))->regionId('cn-hangzhou')->asDefaultClient();
try {
$result = AlibabaCloud::rpc()
->product('Dysmsapi')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->host('dysmsapi.aliyuncs.com')
->options([
'query' => [
'RegionId' => "cn-hangzhou",
'PhoneNumbers' => $mobile,
'SignName' => config('sms.sign_name'),
'TemplateCode' => config('sms.template_code'),
'TemplateParam' => $authCode,
],
])
->request();
// 成功发送后的结果集
//print_r($result->toArray());
// 短信发送成功可以这里进行相关业务逻辑处理
if ($result['Code'] == 'OK') {
return true;
} else {
return false;
}
} catch (ClientException $e) {
//echo $e->getErrorMessage() . PHP_EOL;
} catch (ServerException $e) {
//echo $e->getErrorMessage() . PHP_EOL;
}
}
}
四、blade模板
需要 jquery
@extends('layouts.app')
@section('content')
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-lg-4 col-md-6">
<div class="card shadow-xs stacked">
<div class="pt-3 border-0">
<ul class="nav nav-tabs px-3">
<a href="{{ route('app.oauth.mobile_login') }}" class="nav-link active">{{ __('Mobile') }}{{ __('Login') }}</a>
<a href="{{ route('login') }}" class="nav-link">{{ __('Email') }}{{ __('Login') }}</a>
@if (Route::has('register'))
<a href="{{ route('register') }}" class="nav-link">{{ __('Register') }}</a>
@endif
</ul>
</div>
<div class="card-body">
<form method="POST" action="{{ route('app.oauth.mobile_login') }}">
@csrf
<div class="mb-3">
<label for="mobile" class="form-label">{{ __('手机号') }}</label>
<input id="mobile" type="text" class="form-control @error('mobile') is-invalid @enderror" name="mobile" value="{{ old('mobile') }}" required autocomplete="mobile">
@error('mobile')<span class="invalid-feedback" role="alert"><strong>{{ $message }}</strong></span>@enderror
</div>
<div class="mb-3">
<label for="code" class="form-label">{{ __('验证码') }}</label>
<div class="input-group mb-3">
<input id="code" type="code" class="form-control @error('code') is-invalid @enderror" name="code" required autocomplete="current-code">
@error('code')<span class="invalid-feedback" role="alert"><strong>{{ $message }}</strong></span>@enderror
<button type="button" class="input-group-text" id="postcode" role="button">{{ __('获取验证码') }}</button>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember">{{ __('Remember Me') }}</label>
</div>
</div>
@if (Route::has('password.request'))
<div class="col-md-6 text-end">
<a href="{{ route('password.request') }}" class="link-primary text-decoration-none">{{ __('Forgot Your Password?') }}</a>
</div>
@endif
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary px-4">{{ __('Login') }}</button>
</div>
<div class="mb-0">
<a href="{{ route('app.oauth.redirect', 'qq') }}"><img src="/uploads/system/icon/login-qq.png"></a>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script type="module">
$(document).on("click", "#postcode",function () {
var mobile_number = $('[name="mobile"]').val();
var wait = 60;
$.ajax({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
url: "/auth/mobile_code",
type: "post",
dataType: "json",
data: {"mobile": mobile_number},
success: function (data) {
console.log(data);
if(data.status == 'success'){
var _set = setInterval(function(){
$("#postcode").attr("disabled", true);
$('#postcode').text(wait + '秒后重新发送');
wait-=1;
if(wait <= 0){
$("#postcode").removeAttr("disabled");
$('#postcode').text('获取验证码');
clearInterval(_set);
}
},1000);
}else{
alert(data.message);
}
}
})
})
</script>
@endsection