后台管理部分
一、后台部分用thinkJs和mysql创建后台
1、获取post提交用户名和密码
async loginAction() {
if (this.method == "POST") {
let username = this.post('username')
let password = this.post('password')
let user = await this.model('member').where({ username: username }).find()
if (user.password == this.verifyPassword(password)) {
const token = this.updateAuth(password)
this.json({ state: '登录成功', token: token })
} else {
return this.json({ state: "登录失败" })
}
}
}
verifyPassword(password) {
return think.md5(think.md5("www.cmswing.com") + think.md5(password) + think.md5('Arterli'))
}
2、连接数据库
config/adapter.js
在adapter.js文件处配置mysql的接口
mysql: {
handle: mysql,
database: 'mall',
prefix: '',
encoding: 'utf8',
host: '127.0.0.1',
port: '',
user: 'root',
password: '',
dateStrings: true
}
3、在用户登录的环节中要实现JWT跨域身份验证(JSON WEB TOKEN)
- 用户发送用户名和密码
- 验证用户名和密码,保存验证信息
- 返回口令到前端
- 前端将口令保存
- 等到下次发送请求的时候,将口令发送到服务器
- 服务器可以验证口令,判断用户信息和登录状态
- 更新口令
在controller/base.js
文件下
const jsonwebtoken = require('jsonwebtoken')
authFail() {
this.json({ error: "JWT校验失败" })
return false
}
checkAuth() {
let token = this.ctx.headers['x-token']
const { secret, cookie, expire } = this.config('jwt')
try {
var tokenObj = token ? jsonwebtoken.verify(token, secret) : {}
this.ctx.state.username = tokenObj.name
} catch (error) {
return this.authFail()
}
if (!tokenObj.name) {
return this.authFail()
}
this.updateAuth(token.name)
}
updateAuth(username) {
const userInfo = {
name: username
}
const { secret, cookie, expire } = this.config('jwt')
const token = jsonwebtoken.sign(userInfo, secret, { expireInfo: expire })
this.cookie(cookie, token)//获取口令
this.headers('authoriztion', token)//返回响应头
return token
}
config/config.js
jwt: {
secret: "makamakamaka",
cookie: 'jwt-token',
expire: 3000 //以秒作单位
},
hostIpPort: 'http://127.0.0.1:8360
config/middleware.js
middleware属于中间件
const jwt = require('koa-jwt')
{
handle: 'jwt',
options: {
secret: this.config('jwt')['secret'],
cookie: this.config('jwt')['cookie'],
passthrought: true
}
},
'logic',
'controller'
二、前端接口处理
前端部分由vue-admin-template完成
login/index.js
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.dispatch('user/login', this.loginForm).then(() => {
// this.$router.push({ path: this.redirect || '/' })
//1把路由跳转路径修改
this.$router.push({ path: '/admin' })
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
router/index.js
//2重新设置登录页
{
path: '/',
redirect: '/login'
},
//修改dashboard上的路径
{
path: '/admin',
component: Layout,
redirect: '/admin/dashboard',
children: [{
path: 'dashboard',
name: 'Dashboard',
component: () =>
import ('@/views/dashboard/index'),
meta: { title: '首页看板', icon: 'dashboard' }
}]
}
api/user.js
export function login(data) {
return request({
url: '/user/login/login', //3 改地址
method: 'post',
data
})
}
.env.development
# base api 4
VUE_APP_BASE_API = '/api'
vue.config.js
//5 跨域配置
proxy: {
'/api': {
target: "http://127.0.0.1:8360",
pathRewrite: {
'^/api': ""
}
}
}
premission.js
if (hasToken) {
next()
NProgress.done()
let user = await store.dispatch('user/getInfo')
let userinfo = user.userinfo
let rulelist = user.rulelist
let ruleids = userinfo.rule_ids.split(',')
let ruleArr = {}
rulelist.forEach((item, index) => {
ruleArr[item.name] = item.id
});
if (ruleArr[to.path]) {
if (ruleids.indexOf(String(ruleArr[to.path])) != -1) {
next()
} else {
Message({
message: '您没有权限进入',
type: 'error',
duration: 2 * 1000
})
next('/admin/dashboard')
}
} else {
next()
}
utils/request.js
response => {
const res = response.data
// if the custom code is not 20000, it is judged as an error.
if (response.status !== 200) { //不用它原来的code状态码,需要的是response.status状态码200去验证
Message({
message: res.message || 'Error',
type: 'error',
duration: 2 * 1000
})
router.push('/login') //跳转到登录页面
return Promise.reject(new Error(res.message || 'Error'))
} else {
if (res.error == 'JWT校验失败') {
Message({
message: '请重新登录',
type: 'error',
duration: 2 * 1000
})
router.push('/login')
} else if (response.headers.authorization) {
setToken(response.headers.authorization)
} //如果成功的话,在头上会有之前在后端所定义到的authoriztion字段
return res
}
},
utils/auth.js
const TokenKey = 'jwttoken'
store/modules/user.js
login({ commit }, userInfo) {
const { username, password } = userInfo
return new Promise((resolve, reject) => {
login({ username: username.trim(), password: password }).then(response => {
// const { data } = response由于token在response里面了,所以不需要data去作为解构
commit('SET_TOKEN', response.token)
setToken(response.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
成功之后,会进入登录平台
三、编写后端用户信息接口(实现是用户信息)
thinkJS controller/admin/index.js
__before() {
return this.checkAuth()//检查口令
}
async userInfoAction() {
let username = this.ctx.state.username
//查找用户有没有在后台上有头像文件图片
// let user = await this.model('member').where({ username: username }).find()
let user = await this.model('member').where({ 'cmswing_member.username': username })
.join({
table: "auth_user_role",
join: "left",
as: "l",
on: ['id', 'user_id']
}).join({
table: "auth_role",
join: "left",
as: 'c',
on: ['l.role_id', 'id']
}).field("username,desc,password,mobile,email,role_id,rule_ids").find()
let rulelist = await this.model('auth_rule').order('id').select()
let filepath = think.ROOT_PATH + '/www/static/image/avatar/avatar' + user.id + '.png'
if (think.isFile(filepath)) {
user.avatar = this.config('hostIpPort') + '/static/image/avatar/avatar' + user.id + '.png'
} else {
user.avatar = this.config('hostIpPort') + '/static/image/avatar/avatar' + '.jpg'
}
return this.json({ userinfo: user, rulelist })
}
api/user.js
export function getInfo(token) {
return request({
url: '/admin/index/userInfo',
method: 'get',
})
}
store/modules/user.js
getInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
if (!response.userinfo) {
return reject('Verification failed, please Login again.')
}
const { username, avatar } = response.userinfo
commit('SET_NAME', username)
commit('SET_AVATAR', avatar)
resolve(response)
}).catch(error => {
reject(error)
})
})
},
//注销功能
logout({ commit, state }) {
return new Promise((resolve, reject) => {
removeToken() // must remove token first
resetRouter()
commit('RESET_STATE')
resolve()
})
}