1.登录方法
1.1 传统身份验证的方法
- 用户提交登录信息
- 服务端生成一条记录,其中会说明用户信息
- 服务端返回记录的ID号给客户端
- 这个ID号会被存储在客户端的
Cookie
里,下次用户再向服务端发送请求时可以带着这个Cookie
,这样服务端会验证该Cookie
里的信息,如果找到对应的记录,说明用户通过了身份验证,就把用户请求的数据返回给客户端 - 而上面再服务端生成的就是用户的
Session
,需要再服务端定期清理过期的Session
1.2 基于 token 的登录流程
- 客户端使用用户名跟密码请求登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会签发一个
Token
,再把这个Token
发送给客户端 - 客户端收到
Token
以后可以把它存储起来,比如放在Cookie
里或者Local Storage
里 - 客户端每次向服务端请求资源的时候需要带着服务端签发的
Token
- 服务端收到请求,然后去验证客户端请求里面带着的
Token
,如果验证成功,就向客户端返回请求的数据
1.3 token 作用
- 将
token
存入本地cookie
中,可以保证每次刷新时用户登录状态不丢失 - 通过
token
,还可以获取到用户的其他信息
2. 逻辑代码
2.1. 登录事件
点击`handleLogin`触发`vuex`中`actions`的`Login`派发行为
复制代码
handleLogin() {
this.$store
.dispatch('Login', this.loginForm)
.then(() => {
this.$router.push({ path: '/' });
})
.catch(() => {
})
}
复制代码
2.2. store.js
然后回到vuex
,这里的store.js
改成store
文件夹,分模块管理vuex
// 文件夹结构
|-- store
|-- modules
|-- getters.js
|-- index.js
复制代码
我们划分出,app, user 两个模块,在 user 里控制用户的登录信息,app 中存储应用的状态,如全局loading
或者控制第三方组件的全局大小,如element-ui
中的全局组件size
// index.vue
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
user
},
getters
})
export default store
复制代码
user.js
中存储了登录事件所需的事件和数据,handleLogin
事件触发的是modules
中user
模块的actions
,这里user.js
中的具体方法和state
数据,均是封装过的
2.3 request 请求封装
- 在
utils/auth.js
中封装设置cookie
的方法
// 导入 Cookies
import Cookies from 'js-cookie'
// 设置 cookie name
const TokenKey = 'Admin-Token'
// 获取 Admin-Token 的 cookie
export function getToken() {
return Cookies.get(TokenKey);
}
// setToken
export function setToken(token) {
return Cookies.set(TokenKey, token);
}
// 移除 token
export function removeToken() {
return Cookies.remove(TokenKey)
}
复制代码
- 在
utils/request
中封装axios
请求设置
import axios from 'axios'
import store from '../store'
import { getToken } from '@/utils/auth'
const service = axios.create({
baseURL: 'http://193.112.153.155:3001',
timeout: 5000 // 请求超时时间
})
export default service
复制代码
- 在api/login.js中封装登录api请求
import request from '@/utils/request'
export function login(username, password) {
return request({
url: '/user/login',
method: 'post',
data: {
username,
password
}
})
}
export function getInfo(token) {
return request({
url: '/user/info',
method: 'get',
params: { token }
})
}
export function logout() {
return request({
url: '/user/logout',
method: 'post'
})
}
复制代码
- 再回到modules/user.js中完成登录的
store
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
const user = {
state: {
token: getToken(),
name: '',
avatar: '',
roles: []
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
}
},
actions: {
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
login(username, userInfo.password).then(response => {
const data = response.data;
setToken(data.token)
commit('SET_TOKEN', data.token);
resolve()
}).catch(error => {
reject(error)
})
})
},
// 获取用户信息
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
const data = response.data
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', data.roles)
} else {
reject('getInfo: roles must be a non-null array !')
}
commit('SET_NAME', data.name)
commit('SET_AVATAR', data.avatar)
resolve(response)
}).catch(error => {
reject(error)
})
})
},
// 登出
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
},
// 前端 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
}
}
}
export default user
复制代码
本文仅供个人学习总结使用 参考: