@[Laraval|后端|框架]
完成了注册,接下来要做的就登录和退出登录了
一般用户的登录流程如下:
- 访问登录页面,输入账号密码点击登录;
- 服务器对用户身份进行认证,认证通过后,记录登录状态并进行页面重定向;
- 登录成功后的用户,能够使用退出按钮来销毁当前登录状态;
最后,为了用户的体验,加上记住我,免得再次登录麻烦,是最好不过了
由于HTTP协议的无状态性,想同步两个页面的用户信息,我们需要借助会话在浏览器内存储身份信息
与之前一样,要么直接拷贝控制器基本内容避免命令行操作,否则就使用命令php artisan make::controller SessionsController
生成,相信大家一定很熟悉了。
接下来,我们还需要配置对应的路由,稍微分析一下,路由的功能有显示登录页面,创建新的session,退出时销毁会话,也就是:
HTTP请求 | URL | 动作 | 作用 |
---|---|---|---|
GET | /login | SessionsController@create | 显示登录页面 |
POST | /login | SessionsController@store | 创建新会话(登录) |
DELETE | /logout | SessionsController@destroy | 销毁会话(退出登录) |
转换成代码也就是在`route/web.php加入代码
Route::get('login', 'SessionsController@create')->name('login');
Route::post('login', 'SessionsController@store')->name('login');
Route::delete('logout', 'SessionsController@destroy')->name('logout');
在控制器app/Http/Controllers/SessionsController.php
内加入create动作
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
class SessionsController extends Controller
{
public function create()
{
return view('sessions.create');
}
}
对应的,我们需要创建一个登录页面,在resources/views/sessions/create.blade.php
中创建新视图
@extends('layouts.default')
@section('title', '登录')
@section('content')
<div class="col-md-offset-2 col-md-8">
<div class="panel panel-default">
<div class="panel-heading">
<h5>登录h5>
div>
<div class="panel-body">
@include('shared._errors')
<form method="POST" action="{{ route('login') }}">
{{ csrf_field() }}
<div class="form-group">
<label for="email">邮箱:label>
<input type="text" name="email" class="form-control" value="{{ old('email') }}">
div>
<div class="form-group">
<label for="password">密码:label>
<input type="password" name="password" class="form-control" value="{{ old('password') }}">
div>
<button type="submit" class="btn btn-primary">登录button>
form>
<hr>
<p>还没账号?<a href="{{ route('signup') }}">现在注册!a>p>
div>
div>
div>
@stop
为了创建认证,我们需要在会话控制器内添加store方法啦进行验证
public function store(Request $request)
{
$credentials = $this->validate($request, [
'email' => 'required|email|max:255',
'password' => 'required'
]);
return;
}
但这显然不够,这段代码里只是进行了输入验证,并未要求邮箱和对应密码的匹配性
通过Auth的attempt方法,我们可以快速完成验证
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// 该用户存在于数据库,且邮箱和密码相符合
}
attempt 方法执行的代码逻辑如下:
使用 email 字段的值在数据库中查找;
如果用户被找到:
- 先将传参的 password 值进行哈希加密,然后与数据库中 password 字段中已加密的密码进行匹配;
- 如果匹配后两个值完全一致,会创建一个『会话』给通过认证的用户。会话在创建的同时,也会种下一个名为 laravel_session 的 HTTP Cookie,以此 Cookie 来记录用户登录状态,最终返回 true;
- 如果匹配后两个值不一致,则返回 false;
如果用户未找到,则返回 false。
故还需在return前加入代码
if (Auth::attempt($credentials)) {
// 登录成功后的相关操作
} else {
// 登录失败后的相关操作
}
接下来我们还需要添加认证通过和失败对应的操作
当认证失败时,我们使用danger来提示用户
session()->flash('danger', '很抱歉,您的邮箱和密码不匹配');
成功时,我们要重定向到用户页面
所以逻辑就变成
if (Auth::attempt($credentials)) {
session()->flash('success', '欢迎回来!');
return redirect()->route('users.show', [Auth::user()]);
} else {
session()->flash('danger', '很抱歉,您的邮箱和密码不匹配');
return redirect()->back();
}
注意:在使用Auth前,一定要加上一句
use Auth;
由于添加了用户登录,从网页交互来看,我们也要修改一下导航栏,把已登录和未登录区别开来
小贴士:Laravel 提供了
Auth::check()
方法用于判断当前用户是否已登录,已登录返回 true,未登录返回 false
修改一下header,加上逻辑
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<div class="col-md-offset-1 col-md-10">
<a href="/" id="logo">Sample Appa>
<nav>
<ul class="nav navbar-nav navbar-right">
@if (Auth::check())
<li><a href="#">用户列表a>li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{ Auth::user()->name }} <b class="caret">b>
a>
<ul class="dropdown-menu">
<li><a href="{{ route('users.show', Auth::user()->id) }}">个人中心a>li>
<li><a href="#">编辑资料a>li>
<li class="divider">li>
<li>
<a id="logout" href="#">
<form action="{{ route('logout') }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button class="btn btn-block btn-danger" type="submit" name="button">退出button>
form>
a>
li>
ul>
li>
@else
<li><a href="{{ route('help') }}">帮助a>li>
<li><a href="{{ route('login') }}">登录a>li>
@endif
ul>
nav>
div>
div>
header>
注意,在这里使用了bootstrap的下拉菜单,所以要把jQuery和boostrap.js文件包含进去,不然下拉菜单就没法用啦
在这里要关注一下退出的代码
<form action="{{ route('logout') }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button class="btn btn-block btn-danger" type="submit" name="button">退出button>
form>
其实是一个表单,触发了DELETE
添加这个功能后,体验会更好
我们修改用户的store方法
在刷新前加入
Auth::login($user);
即可
我们通过laravel自带的
Auth::logout()
实现退出
加上destroy方法
class SessionsController extends Controller
{
.
.
.
public function destroy()
{
Auth::logout();
session()->flash('success', '您已成功退出!');
return redirect('login');
}
}
在 Laravel 的默认配置中,如果用户登录后没有使用『记住我』功能,则登录状态默认只会被记住两个小时。如果使用了『记住我』功能,则登录状态会被延长到五年
首先,在登录页上加上记住我的复选框
<div class="checkbox">
<label><input type="checkbox" name="remember"> 记住我label>
div>
Auth::attempt() 方法可接收两个参数,第一个参数为需要进行用户身份认证的数组,第二个参数为是否为用户开启『记住我』功能的布尔值。接下来让我们修改会话控制器中的 store 方法,为 Auth::attempt() 添加『记住我』参数
if (Auth::attempt($credentials, $request->has('remember'))) {
session()->flash('success', '欢迎回来!');
return redirect()->route('users.show', [Auth::user()]);
} else {
session()->flash('danger', '很抱歉,您的邮箱和密码不匹配');
return redirect()->back();
}