[Day 31] 会员登入及登出(三)

今天我们来把登入的功能完成.

会员登入

当验证通过之後,
就可以正常登入,
在登入的时候,
我们会透过session来记录会员的编号,
来作为会员已登入的验证.

app/Http/Controllers/UserAuthController.php的signInProcess的方法

//前面省略

//session纪录会员编号
session()->put('user_id', $User->id);

//重新导向到原先使用者造访页面,没有尝试造访页则重新导向回自我介绍页
return redirect()->intended('/admin/user');

使用者在浏览网站的时候,
有可能会因为不同的原因而进入登入页,
这时候如果能够重新回到登入前的页面,
是比较好的使用者体验,
Laravel也考虑到了这一点,
所以提供redirect()->intended()方法,
来处理重新导向的功能,
intended方法里面可以放预设的页面,
如果使用者是直接进入登入页,
就会重新导向到指定的页面.

在这个部落格网站里面,
会有所谓的前台後台,
以我所认知的部落格而言,
每一个使用者的权限都是一样的,
可以编辑属於自己的後台,
也可能观看所有人的前台,
当我们要观看前台的时候不需要登入,
(但是要留言的话需要登入)
不过当我们要进入後台的话就需要验证你是否已登入,
我们在登入完毕之後会进入到後台编辑自我介绍的部分.

Session的设定

所有session的设定都放在config/session.php这个设定档案内,

其中有一行

'driver' => env('SESSION_DRIVER', 'file'),

表示要用甚麽方法来储存session,
Laravel有提供filecookiedatabaseapcmemcachedredisarray等等储存方式,
如果只有一台主机,
大部分都使用file就可以了,
可是如果有好几台主机,
假如没办法做到同步,
就会有「明明已经登入,系统却判断为没有登入」的问题,
就可以使用database、redis或memchached等等的方式,
我们这里只考虑一台主机的情况,
所以不需要修改session的设定.

登入的判断

所以我们要判断是否会员已登入,
就是透过session的user_id来判断,
我们用Laravel提供的session()->has()方法来判断是否已经登入.

if(session()->has('user_id'))

登出的动作

既然我们是透过session来判断会员登入,
登出的时候就是透过Laravel提供的session()->forget()方法来清除session资料,
之後再重新导向到首页.

app/Http/Controllers/UserAhthController.php的signOut方法

//登出
public function signOut()
{
    //清除Session
    session()->forget('user_id');

    //重新导向回首页
    return redirect('/');
}

重新修改Menu

我们之前把所有的功能都放在Menu上,
但是这样子是很奇怪的,
如果没有登入,
就不应该会有登出的功能,
在这里我们分成几种情况,
一种是尚未登入的情况,
会有部落格注册登入等页签, => 在此将原先的首页改成部落格
一种是已登入而且在前台,
会有部落格进入後台登出等页签
另外一种是已登入而且在後台,
会有自我介绍心情随笔回到前台等页签

我们把resources/views/layout/master修改如下


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>@yield('title')</title>
        <script src="/js/app.js"></script>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
        <link rel="stylesheet" href="/css/app.css?<?php echo date("mj", time())?>">
    </head>
    <boby>
        <div class="toolbar_section">
            <span class="toolbar_title">@yield('title')</span>
            <span class="toolbar_title2">小鱼</span>
            
        </div>

        <div class="container">
            <div class="col-sm-1 form background_white">
                <ul class="nav nav-pills nav-stacked">
                @if($page == "admin" && session()->has('user_id'))
                    <!-- 自我介绍 -->
                    <li 
                    @if($name == "user")
                        class="active"
                    @endif
                    >
                        <a href="/admin/user">自我介绍</a>
                    </li>
                    <!-- 心情随笔 -->
                    <li 
                    @if($name == "mind")
                        class="active"
                    @endif
                    >
                        <a href="/admin/mind">心情随笔</a>
                    </li>
                    <!-- 回到前台 -->
                    <li>
                        <a href="/">部落格</a>
                    </li>
                @else
                    <!-- 首页 -->
                    <li 
                    @if($name == "home")
                        class="active"
                    @endif
                    >
                        <a href="/">部落格</a>
                    </li>
                    @if(session()->has('user_id'))
                        <!-- 自我介绍 -->
                        <li>
                            <a href="/admin/user">进入後台</a>
                        </li>
                    @else
                        <!-- 注册 -->
                        <li 
                        @if($name == "sign_up")
                            class="active"
                        @endif
                        >
                            <a href="/user/auth/sign-up">注册</a>
                        </li>
                        <!-- 登入 -->
                        <li 
                        @if($name == "sign_in")
                            class="active"
                        @endif
                        >
                            <a href="/user/auth/sign-in">登入</a>
                        </li>

                    @endif
                @endif
                @if(session()->has('user_id'))
                    <!-- 登出 -->
                    <li>
                        <a href="/user/auth/sign-out">登出</a>
                    </li>
                @endif
                </ul>
            </div>
            <div class="col-sm-11 background_white2">
                @yield('content')
            </div>
        </div>
    </body>
</html>

而routes/web.php也修改如下

<?php

use Illuminate\Support\Facades\Route;

//首页
Route::get('/', 'HomeController@indexPage');

Route::group(['prefix' => 'user'], function(){
    //使用者验证
    Route::group(['prefix' => 'auth'], function(){
        //使用者注册画面
        Route::get('/sign-up', 'UserAuthController@signUpPage');
        //处理注册资料
        Route::post('/sign-up', 'UserAuthController@signUpProcess');
        //使用者登入画面
        Route::get('/sign-in', 'UserAuthController@signInPage');
        //处理登入资料
        Route::post('/sign-in', 'UserAuthController@signInProcess');
        //处理登出资料
        Route::get('/sign-out', 'UserAuthController@signOut');
    });
});

Route::group(['prefix' => 'admin'], function(){
    //自我介绍相关
    Route::group(['prefix' => 'user'], function(){
        //自我介绍页面
        Route::get('/', 'AdminController@editUserPage');
        //处理自我介绍资料
        Route::post('/', 'UserAuthController@editUserProcess');
    });

    //心情随笔相关
    Route::group(['prefix' => 'mind'], function(){
        //心情随笔列表页面
        Route::get('/', 'AdminController@mindListPage');
        //新增心情随笔资料
        Route::get('/add', 'AdminController@addMindPage');
        //处理心情随笔资料
        Route::post('/edit', 'AdminController@editMindProcess');
        //单一资料
        Route::group(['prefix' => '{mind_id}'], function(){
            //编辑心情随笔资料
            Route::get('/edit', 'AdminController@editMindPage');
            //删除心情随笔资料
            Route::get('/delete', 'AdminController@deleteMindProcess');
        });
    });

});
?>

在这里我们新增一个变数$page来判断是否是後台,
所以之前的Controller都要加上$page这个变数,
否则就会出错,
我们重新修改HomeController和UserAuthController两个档案

app/Http/Controllers/HomeController.php

<?PHP
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Module\ShareData;

class HomeController extends Controller
{
    public $page = "";
    //首页
    public function indexPage()
    {
        $name = 'home';
        $binding = [
            'title' => ShareData::TITLE,
            'page' => $this->page,
            'name' => $name,
        ];
        return view('home', $binding);
    }
}
?>

app/Http/Controllers/UserAhthController.php

<?PHP
namespace App\Http\Controllers;

use Mail;
use Hash;
use Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use App\Module\ShareData;
use App\Entity\User;

class UserAuthController extends Controller
{
    public $page = "";
    //使用者注册画面
    public function signUpPage()
    {
        $name = 'sign_up';
        $binding = [
            'title' => ShareData::TITLE,
            'page' => $this->page,
            'name' => $name,
        ];
        return view('user.sign-up', $binding);
    }

    //处理注册资料
    public function signUpProcess()
    {
        //接收输入资料
        $input = request()->all();

        //验证规则
        $rules = [
            //昵称
            'name' => [
                'required',
                'max:50',
            ],
            //帐号(E-mail)
            'account' => [
                'required',
                'max:50',
                'email',
            ],
            //密码
            'password' => [
                'required',
                'min:5',
            ],
            //密码验证
            'password_confirm' => [
                'required',
                'same:password',
                'min:5'
            ],
        ];

        //验证资料
        $validator = Validator::make($input, $rules);

        if($validator->fails())
        {
            //资料验证错误
            return redirect('/user/auth/sign-up')
                    ->withErrors($validator)
                    ->withInput();
        }

        $input['password'] = Hash::make($input['password']);

        //Log::notice(print_r($input, true));

        //启用纪录SQL语法
        DB::enableQueryLog();

        //新增使用者资料
        User::create($input);

        //取得目前使用过的SQL语法
        Log::notice(print_r(DB::getQueryLog(), true));

        //寄送注册通知信
        $mail_binding = [
            'name' => $input['name']
        ];

        Mail::send('email.signUpEmailNotification', $mail_binding,
        function($mail) use ($input){
            //收件人
            $mail->to($input['account']);
            //寄件人
            $mail->from('[email protected]');
            //邮件主旨
            $mail->subject('恭喜注册Laravel部落格成功!');
        });

        //重新导向到登入页
        return redirect('/user/auth/sign-in');
    }

    //使用者登入画面
    public function signInPage()
    {
        $name = 'sign_in';
        $binding = [
            'title' => ShareData::TITLE,
            'page' => $this->page,
            'name' => $name,
        ];
        return view('user.sign-in', $binding);
    }

    //处理登入资料
    public function signInProcess()
    {
        //接收输入资料
        $input = request()->all();

        //验证规则
        $rules = [
            //帐号(E-mail)
            'account' => [
                'required',
                'max:50',
                'email',
            ],
            //密码
            'password' => [
                'required',
                'min:5',
            ],
        ];

        //验证资料
        $validator = Validator::make($input, $rules);

        if($validator->fails())
        {
            //资料验证错误
            return redirect('/user/auth/sign-in')
                ->withErrors($validator)
                ->withInput();
        }

        //取得使用者资料
        $User = User::where('account', $input['account'])->first();

        if(!$User)
        {
            //帐号错误回传错误讯息
            $error_message = [
                'msg' => [
                    '帐号输入错误',
                ],
            ];

            return redirect('/user/auth/sign-in')
                ->withErrors($error_message)
                ->withInput();
        }

        //检查密码是否正确
        $is_password_correct = Hash::check($input['password'], $User->password);

        if(!$is_password_correct)
        {
            //密码错误回传错误讯息
            $error_message = [
                'msg' => [
                    '密码输入错误',
                ],
            ];

            return redirect('/user/auth/sign-in')
                    ->withErrors($error_message)
                    ->withInput();
        }

        //session纪录会员编号
        session()->put('user_id', $User->id);

        //重新导向到原先使用者造访页面,没有尝试造访页则重新导向回自我介绍页
        return redirect()->intended('/admin/user');
    }

    //登出
    public function signOut()
    {
        //清除Session
        session()->forget('user_id');

        //重新导向回首页
        return redirect('/');
    }
}
?>

以下是未登入的画面
https://ithelp.ithome.com.tw/upload/images/20201003/20105694P00xIiJu10.png

以下是登入後的前台画面
https://ithelp.ithome.com.tw/upload/images/20201003/201056941RXxKFPWka.png

至於登入後的後台画面明天才开始做,
不过因为登入之後会直接导到後台,
目前还没有Controller跟页面,
各位大大也可以尝试根据目前所学的,
自己先做一个页面代替,
明天再正式做新的页面.


<<:  [Day 30] 会员登入及登出(二)

>>:  还在烦恼CSS flex怎麽调整吗?也许你该试试Chrome 90 的新功能 — flexbox Editor

Day 30: 完赛总结

终於完赛啦! 这次挑战赛仅聚焦於结构化资料的资料分析,非结构化资料(图片声音影片等等),就需要用到深...

Re: 新手让网页 act 起来: Day25 - useMemo 和 useCallback

前言 在前面几天介绍了使用了 useCallback 或 useMemo 来做效能优化,不知道会不会...

第一次的爬虫(2)

那我就延续上一篇的实作吧! 已经将会用到的套件装上,并且在网站的控制室找到所需的资讯位置,接下来就是...

Day 5 - 使用JWT Token帮Laravel 8.0做Authentication

Introduce 为了API的安全性,本次跟各位介绍透过JWT Token来帮API做身分验证,简...

把 HackMD 当成网站後台

把 HackMD 当成网站後台 前面已经分享了如何完全透过网页的操作,就可以把 VuePress 网...