目录
用户登录
1.用户登录接口
在route\route.php中添加路由规则。
Route::post('user/login', 'api/User/login');
打开application\api\controller\User.php,编写login()方法。
public function login()
{
$data = [
'name' => $this->request->post('name/s', '', 'trim'),
'password' => $this->request->post('password/s', '')
];
$validate = new UserValidate;
if (!$validate->check($data)) {
$this->error('登录失败:' . $validate->getError() . '。');
}
}
打开application\api\library\Auth.php,编写login()方法。
public function login($name, $password)
{
$user = UserModel::get(['name' => $name]);
if (!$user) {
$this->setError('用户不存在');
return false;
}
if ($user->password != $this->passwordMD5($password, $user->salt)) {
$this->setError('用户名或密码不正确');
return false;
}
return [
'id' => $user->id,
'name' => $user->name,
'is_active' => $user->is_active,
'role' => $user->role
];
}
打开application\api\controller\User.php,完成登录操作。
public function login()
{
……(原有代码)
$result = $this->auth->login($data['name'], $data['password']);
if (!$result) {
$this->error('登录失败:' . $this->auth->getError() . '。');
}
$this->success('登录成功。', null, $result);
}
2.用户登录页面
打开src\pages\Login.vue,重新编写登录页面。
结构:
<template>
<div class="login">
<div class="row">
<div class="col login-logo">
<h2>LightBBS</h2>
</div>
<div class="col login-title">用户登录</div>
</div>
<div class="form-group">
<input type="text" class="form-control" placeholder="用户名" v-model="form.name" />
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="密码" v-model="form.password" />
</div>
<div class="form-group">
<button class="btn btn-success login-submit" @click="login">登录</button>
</div>
</div>
</template>
逻辑:
<script>
export default {
data () {
return {
form: {
name: '',
password: '',
}
}
},
methods: {
login () {
// 用户登录
}
}
}
</script>
样式:
<style scoped>
.login {
margin-top: 20px;
padding-top: 30px;
padding-left: 15px;
padding-right: 15px;
border-radius: 0px;
border: 1px solid #dde2e8;
background: #ffffff;
}
.login-logo {
text-align: left;
color: #fd7e14;
}
.login-title {
text-align: right;
font-size: 16px;
line-height: 60px;
}
.login-submit {
width: 100%;
}
</style>
页面效果:
发送请求:
login () {
this.$http.post('user/login', this.form).then(res => {
if (res.data.code === 0) {
this.$toastr.e(res.data.msg)
} else if (res.data.code === 1) {
this.$toastr.s(res.data.msg)
}
}).catch(() => {
this.$toastr.e('登录失败,服务器异常。')
})
}
登录成功:
3.记住登录状态
由于Vue请求服务器属于跨域请求,不能使用Cookie保存服务器返回的SessionID,所以换成用localStorage来保存SessionID。
打开application\api\library\Auth.php,保存sessionName。
class Auth
{
protected static $instance;
protected $sessionName = 'user';
……(原有代码)
}
修改login()方法,保存Session,并返回SessionId。
public function login($name, $password)
{
……(原有代码)
Session::set($this->sessionName, ['id' => $user->id]);
return [
'session_id' => session_id(),
……(原有代码)
];
}
上述代码将用户id保存在服务器端Session中,然后将SessionID返回给客户端。
打开application\api\controller\Common.php,关闭Cookies中的SessionID。
protected function initialize()
{
ini_set('session.use_cookies', 0);
……(原有代码)
}
查看效果
修改src\config.js,将服务器返回的SessionId保存到localStorage。
vue.prototype.$config = {
……(原有代码)
getAuthorization () {
return localStorage.getItem('Authorization');
},
setAuthorization (Authorization) {
localStorage.setItem('Authorization', Authorization);
}
}
修改src\pages\Login.vue,在登录成功后,将SessionId保存起来。
if (res.data.code === 0) {
this.$toastr.e(res.data.msg)
} else if (res.data.code === 1) {
this.$toastr.s(res.data.msg)
this.$config.setAuthorization(res.data.data.session_id)
}
修改src\http.js,在发送请求的时候,将SessionId放入请求头中发送。
obj.interceptors.request.use(function (req) {
Loading.start()
req.headers.Authorization = config.getAuthorization()
return req
})
查看效果:
4.获取用户信息
在src\components\Header.vue中获取用户信息。
<script>
export default {
created () {
this.getLoginUser()
},
methods: {
getLoginUser () {
this.$http.get('user/userinfo').then(res => {
if (res.data.code === 0) {
this.$toastr.e('未登录。')
} else if (res.data.code === 1) {
window.console.log(res.data.data)
}
}).catch(() => {
this.$toastr.e('获取用户信息失败。')
})
}
}
}
</script>
打开route\route.php,编写服务器端接口的路由。
Route::get('user/userinfo', 'api/User/userinfo');
打开application\api\controller\User.php,编写userinfo()方法。
public function userinfo()
{
}
在application\api\library\Auth.php中获取并保存登录的用户。
protected $sessionName = 'user';
protected $loginUser;
编写getSession()方法,从请求头中获取SessionID。
protected function getSession()
{
if ($id = request()->header('Authorization')) {
Session::init(['id' => $id]);
}
return Session::get($this->sessionName . '.id');
}
编写getLoginUser()方法,获取用户信息。
public function getLoginUser($field = null)
{
$id = $this->getSession();
if (!$this->loginUser && $id) {
$this->loginUser = UserModel::get($id);
}
return $field ? $this->loginUser[$field] : $this->loginUser;
}
打开application\api\controller\User.php,编写userinfo()方法。
public function userinfo()
{
$user = $this->auth->getLoginUser();
$this->success('', null, [
'id' => $user->id,
'name' => $user->name,
'is_active' => $user->is_active,
'role' => $user->role
]);
}
在application\api\library\Auth.php中添加isLogin()方法。
public function isLogin()
{
return $this->getLoginUser();
}
在application\api\controller\Common.php中判断用户是否已经登录。
class Common extends Controller
{
protected $auth;
protected $user;
protected $checkLoginExclude = [];
protected function initialize()
{
ini_set('session.use_cookies', 0);
$this->auth = Auth::getInstance();
$action = $this->request->action();
if (!in_array($action, $this->checkLoginExclude)) {
if (!$this->auth->isLogin()) {
$this->error('您还没有登录。');
}
$this->user = $this->auth->getLoginUser();
}
}
}
打开application\api\controller\User.php,添加不需要验证登录的方法。
class User extends Common
{
protected $checkLoginExclude = ['login', 'register'];
……(原有代码)
}
访问测试。每次刷新页面,就会获取用户信息并显示在控制台中
5.保存用户信息
在获取到用户信息后,将用户信息保存到store。
安装vuex。
npm install vuex@3.1.2 --save
创建src\store\index.js。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {}
const getters = {}
const actions = {}
const mutations = {}
export default new Vuex.Store({
state,
getters,
actions,
mutations
})
在state中保存用户信息。
const state = {
user: {
id: 0,
name: '',
is_active: false,
role: 'user'
},
isLogin: null // null:未知,true:已登录,false:未登录
}
在mutations中编写setUser()方法。
const mutations = {
setUser (state, user) {
if (user) {
state.user.id = user.id
state.user.name = user.name
state.user.is_active = user.is_active
state.user.role = user.role
state.isLogin = true
} else {
state.isLogin = false
}
},
}
在src\main.js中导入。
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
……(原有代码)
new Vue({
render: h => h(App),
router,
store
}).$mount('#app')
修改src\components\Header.vue。
getLoginUser () {
this.$http.get('user/userinfo').then(res => {
if (res.data.code === 0) {
this.$store.commit('setUser', false)
} else if (res.data.code === 1) {
this.$store.commit('setUser', res.data.data)
}
}).catch(() => {
this.$toastr.e('获取用户信息失败。')
})
},
在登录和注册成功后保存用户信息。
打开src\pages\Login.vue,在登录成功以后,保存用户信息,并跳转首页。
login () {
this.$http.post('user/login', this.form).then(res => {
if (res.data.code === 0) {
this.$toastr.e(res.data.msg)
} else if (res.data.code === 1) {
this.$store.commit('setUser', res.data.data)
this.$config.setAuthorization(res.data.data.session_id)
this.$router.replace({ name: 'home' })
}
}).catch(() => {
this.$toastr.e('登录失败,服务器异常。')
})
}
在注册成功后,保存用户信息。先在服务器端返回用户信息。
public function register(array $data)
{
……(原有代码)
Session::set($this->sessionName, ['id' => $user->id]);
return [
'session_id' => session_id(),
……(原有代码)
];
}
打开src\pages\Register.vue,保存用户信息。
register () {
……(原有代码)
this.$http.post('user/register', this.form).then(res => {
if (res.data.code === 0) {
this.$toastr.e(res.data.msg)
} else if (res.data.code === 1) {
this.$toastr.s(res.data.msg)
this.$store.commit('setUser', res.data.data)
this.$config.setAuthorization(res.data.data.session_id)
}
}).catch(() => {
this.$toastr.e('操作失败,服务器异常。')
})
}
6.显示用户信息
修改src\components\Header.vue。
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['user', 'isLogin'])
},
……(原有代码)
}
</script>
修改页面结构,在未登录时显示“登录”和“注册”,已登录时显示用户名。
<div class="collapse navbar-collapse justify-content-between" id="collapsibleNavbar">
<div>
<input class="form-control" type="text" placeholder="Search" />
</div>
<ul class="navbar-nav header-nav" v-if="isLogin">
<li class="nav-item">
<router-link class="nav-link" :to="{ name: 'user' }">
<i class="fa fa-user"></i>
{{ user.name }}
<span class="small text-danger" v-show="!user.is_active">(待验证)</span>
</router-link>
</li>
</ul>
<ul class="navbar-nav header-nav" v-if="isLogin === false">
……(原有代码)
</ul>
</div>
添加样式。
.header-nav {
……(原有代码)
.fa-user {
margin-left: 2px;
margin-right: 5px;
}
}
在src\router\index.js中添加user路由。
routes: [
……(原有代码)
{ path: '/user', name: 'user', component: resolve => require(['@/pages/User.vue'], resolve) },
],
创建src\pages\User.vue文件。
<template>
<div>
用户信息
</div>
</template>
页面效果:
7.用户退出
在src\components\Header.vue中添加退出链接。
<ul class="navbar-nav header-nav" v-if="isLogin">
……(原有代码)
<li class="nav-item">
<div @click="logout" class="nav-link logout">
<i class="fa fa-sign-out"></i>退出
</div>
</li>
</ul>
添加样式。
.header-nav {
……(原有代码)
.fa-sign-out {
margin-right: 5px;
}
.logout {
cursor: pointer;
}
}
编写logout()方法。
methods: {
……(原有代码)
logout () {
this.$http.post('user/logout').then(() => {
this.$store.commit('logout')
this.$config.setAuthorization('')
}).catch(() => {
this.$toastr.e('操作失败,服务器异常。')
})
}
}
在src\store\index.js中编写logout()方法。
const mutations = {
……(原有代码)
logout (state) {
state.user = {
id: 0,
name: '',
is_active: false,
role: 'user'
}
state.isLogin = false
},
}
打开route\route.php,编写服务器端接口。
Route::post('user/logout', 'api/User/logout');
打开application\api\controller\User.php,编写logout()方法。
public function logout()
{
}
打开application\api\library\Auth.php,编写logout()方法。
public function logout()
{
return Session::delete($this->sessionName);
}
打开application\api\controller\User.php,在logout()方法中进行调用。
public function logout()
{
$this->auth->logout();
}