Laravel——Web开发实战之路(九)
@[Laraval|后端|框架]
前言
之前已经完成了用户的注册,登录,退出等功能,接下来要做的就是用户的操作了,类似于编辑资料等等
编辑表单
由于之前我们已经用resourse
方法为用户添加了完整的动作,所以我们不需要再添加编辑界面的路由
Route::get('/users/{user}/edit', 'UsersController@edit')->name('users.edit');
在用户控制器加入编辑用户的操作
public function edit(User $user)
{
return view('users.edit', compact('user'));
}
执行了以下操作
- 利用了 Laravel 的『隐性路由模型绑定』功能,直接读取对应 ID 的用户实例
user,未找到则报错;−将查找到的用户实例
u
s
e
r
,
未
找
到
则
报
错
;
−
将
查
找
到
的
用
户
实
例
user 与编辑视图进行绑定
接下来,只要为用户添加 resources/views/users/edit.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')
<div class="gravatar_edit">
<a href="http://gravatar.com/emails" target="_blank">
<img src="{{ $user->gravatar('200') }}" alt="{{ $user->name }}" class="gravatar"/>
</a>
</div>
<form method="POST" action="{{ route('users.update', $user->id )}}">
{{ method_field('PATCH') }}
{{ csrf_field() }}
<div class="form-group">
<label for="name">名称:</label>
<input type="text" name="name" class="form-control" value="{{ $user->name }}">
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="text" name="email" class="form-control" value="{{ $user->email }}" disabled>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control" value="{{ old('password') }}">
</div>
<div class="form-group">
<label for="password_confirmation">确认密码:</label>
<input type="password" name="password_confirmation" class="form-control" value="{{ old('password_confirmation') }}">
</div>
<button type="submit" class="btn btn-primary">更新</button>
</form>
</div>
</div>
</div>
@stop
同时添加样式
.gravatar_edit {
margin: 15px auto;
text-align: center;
}
gravatar_edit.gravatar {
float: none;
max-width: 100px;
}
最后,我们还要在导航栏中添加入口
resources/views/layouts/_header.blade.php
<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 App</a>
<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="{{ route('users.edit', Auth::user()->id) }}">编辑资料</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>
编辑失败
提交后,我们还需要用用户控制器的update方法及时处理提交的消息
public function update(User $user, Request $request)
{
$this->validate($request, [
'name' => 'required|max:50',
'password' => 'required|confirmed|min:6'
]);
$user->update([
'name' => $request->name,
'password' => bcrypt($request->password),
]);
return redirect()->route('users.show', $user->id);
}
一开始验证提交的 内容。在进行更新操作,最后重定向到个人页面
编辑成功
成功自然要提示一波啦,所以对逻辑稍稍进行优化
public function update(User $user, Request $request)
{
$this->validate($request, [
'name' => 'required|max:50',
'password' => 'nullable|confirmed|min:6'
]);
$data = [];
$data['name'] = $request->name;
if ($request->password) {
$data['password'] = bcrypt($request->password);
}
$user->update($data);
session()->flash('success', '个人资料更新成功!');
return redirect()->route('users.show', $user->id);
}
权限系统
现在虽然可以登录和注册,但是明显还存在两个安全漏洞
- 未登录用户可以访问 edit 和 update 动作
- 登录用户可以更新其它用户的个人信息
因为这两个动作都未和用户自己绑定
检验登录
Laravel 中间件 (Middleware) 为我们提供了一种非常棒的过滤机制来过滤进入应用的 HTTP 请求,例如,当我们使用 Auth 中间件来验证用户的身份时,如果用户未通过身份验证,则 Auth 中间件会把用户重定向到登录页面。如果用户通过了身份验证,则 Auth 中间件会通过此请求并接着往下执行。Laravel 框架默认为我们内置了一些中间件,例如身份验证、CSRF 保护等
使用Auth过滤用户动作
public function __construct()
{
$this->middleware('auth', [
'except' => ['show', 'create', 'store']
]);
}
__construct
是构造方法,希望show,create,store直接执行,过滤edit等
Laravel 提供的 Auth 中间件在过滤指定动作时,如该用户未通过身份验证(未登录用户),默认将会被重定向到 /login 登录页面
用户只能编辑自己的资料
Laravel使用授权策略对操作权限进行检测
首先,使用php artisan make:policy UserPolicy
生成授权策略文件
app/Policies/UserPolicy.php
<?php
namespace App\Policies;
use Illuminate\Auth\Access\HandlesAuthorization;
use App\Models\User;
class UserPolicy
{
use HandlesAuthorization;
public function update(User $currentUser, User $user)
{
return $currentUser->id === $user->id;
}
}
update 方法接收两个参数,第一个参数默认为当前登录用户实例,第二个参数则为要进行授权的用户实例。当两个 id 相同时,则代表两个用户是相同用户,用户通过授权,可以接着进行下一个操作。如果 id 不相同的话,将抛出 403 异常信息来拒绝访问
然后在AuthServiceProvider
类中对授权策略进行设置
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
\App\Models\User::class => \App\Policies\UserPolicy::class,
];
在用户控制器添加Authorize方法进行检验
$this->authorize('update', $user);
剩下的完全无坑,一路按照书走就ok了