import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify'
import axios from 'axios'
import VueAxios from 'vue-axios'
import VueCookies from 'vue-cookies'
// 使用Vue.use的方式装载组件可以不破坏Vue的原型属性
Vue.use(VueAxios, axios)
// 使用vue.use添加vue-cookies
Vue.use(VueCookies)
Vue.config.productionTip = false
new Vue({
router,
store,
vuetify,
render: h => h(App)
}).$mount('#app')
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 获取部分请求需要用到的认证,目前是access token
accessToken: '',
refreshToken: '',
// 代表用户自身,最终不一定会以这种方式呈现
user: {
id: null,
username: '',
password: '',
enabled: true,
firstName: '',
lastName: '',
gender: 0,
phone: '',
email: '',
icon: '',
birthday: new Date().toISOString().substr(0, 10),
joinedDate: new Date().toISOString().substr(0, 10),
// 和用户相关的一些链接,比如用户自身的描述
_links: []
}
},
mutations: {
// 初始化用户
initUser (state) {
state.user = {
id: null,
username: '',
password: '',
enabled: true,
firstName: '',
lastName: '',
gender: 0,
phone: '',
email: '',
icon: '',
birthday: new Date().toISOString().substr(0, 10),
joinedDate: new Date().toISOString().substr(0, 10),
// 和用户相关的一些链接,比如用户自身的描述
_links: []
}
},
// 登录后设置user
setUser (state, user) {
// 设置用户信息
state.user = user
// 将用户生日修改为正确格式
state.user.birthday = state.user.birthday == null ? null : state.user.birthday.substr(0, 10)
// 将user存储在cookies中
Vue.$cookies.set('user', state.user, 7200)
},
// 注销后清除user
removeUser (state) {
this.commit('initUser')
// 清除cookies
if (Vue.$cookies.isKey('user')) {
Vue.$cookies.remove('user')
}
},
// 初始化token
initToken (state) {
state.accessToken = ''
state.refreshTOken = ''
},
// 设置token
setToken (state, data) {
state.accessToken = data.access_token
state.refreshToken = data.refresh_token
Vue.$cookies.set('accessToken', state.accessToken, 7200)
Vue.$cookies.set('refreshToken', state.refreshToken, 86400)
},
// 清除token
removeToken (state) {
this.commit('initToken')
// 清除缓存
if (Vue.$cookies.isKey('accessToken')) {
Vue.$cookies.remove('accessToken')
}
if (Vue.$cookies.isKey('refreshToken')) {
Vue.$cookies.remove('refreshToken')
}
},
// 页面加载时获取用户
loadUser (state) {
if (Vue.$cookies.isKey('user')) {
state.user = Vue.$cookies.get('user')
// 同时获取accessToken和refreshToken
if (Vue.$cookies.isKey('accessToken')) {
state.accessToken = Vue.$cookies.get('accessToken')
}
if (Vue.$cookies.isKey('refreshToken')) {
state.refreshToken = Vue.$cookies.get('refreshToken')
}
} else if (Vue.$cookies.isKey('refreshToken')) {
// access token过期,但是可以刷新token
const refreshToken = Vue.$cookies.get('refreshToken')
const qs = require('qs')
const data = qs.stringify({
refresh_token: refreshToken,
client_id: 'kmhc',
client_secret: '123456',
grant_type: 'refresh_token'
})
Vue.axios.post('http://127.0.0.1:9001/oauth/token', data)
.then(response => {
// 成功刷新令牌,调用checkAccessToken获取用户信息
this.commit('setToken', response.data)
this.commit('checkAccessToken', response.data.access_token)
})
} else {
this.commit('initUser')
}
},
checkAccessToken (state, accessToken) {
// 首先检查access_token的有效性
Vue.axios.get('http://127.0.0.1:9001/oauth/check_token', {
params: {
token: accessToken
}
}).then(response => {
// 请求成功,判断active是否为true,获取username
if (response.data.active) {
const username = response.data.user_name
// 继续发送请求,获取具体用户信息
Vue.axios.get('http://127.0.0.1:9001/api/users/search/findByUsername', {
params: {
username: username
}
}).then(response => {
this.commit('setUser', response.data)
})
}
})
}
},
actions: {
// 设置user的异步方法,可以明显的感觉到延迟降低
setUser (context, user) {
context.commit('setUser', user)
},
// 设置token的异步方法
setToken (context, data) {
context.commit('setToken', data)
}
},
modules: {
}
})
// 登录功能
login () {
// 首先验证表单填写的正确性
const valid = this.$refs.loginForm.validate()
if (valid) {
// 向授权服务器发送请求,获取access token,请求时x-www-form-urlencoded格式
const qs = require('qs')
const data = qs.stringify({
client_id: 'kmhc',
client_secret: '123456',
grant_type: 'password',
username: this.form.username,
password: this.form.password
})
this.axios.post('http://127.0.0.1:9001/oauth/token', data)
.then(response => {
// 授权成功,设置token
this.$store.commit('setToken', response.data)
// 并且获取用户详情,这里不需要验证access token以获取用户名,因为用户名已有
this.axios.get('http://127.0.0.1:9001/api/users/search/findByUsername', {
params: {
username: this.form.username
}
}).then(response => {
// 异步设置user
this.$store.dispatch('setUser', response.data)
// 设置完成后,跳转到主页
this.$router.push({
name: 'Home'
})
}).catch(error => {
console.log(error)
// 用户认证错误,显示消息条
this.snackbar = true
})
})
}
}
<script>
export default {
name: 'App',
data: () => ({
// 控制导航侧栏的显示和隐藏
drawer: true
}),
methods: {
// 通过视图的名字跳转到特定视图,一般用作主页,登录页,注册页等
open (name) {
// 需要先判断当前路由名称是否和目标路由一致,如果一致就不跳转
if (this.$route.name !== name) {
this.$router.push({
name: name
})
}
},
// 注销
logout () {
this.$store.commit('removeUser')
}
},
created () {
// 初始化时加载user
this.$store.commit('loadUser')
}
}
script>
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify'
import axios from 'axios'
import VueAxios from 'vue-axios'
import VueCookies from 'vue-cookies'
// 使用Vue.use的方式装载组件可以不破坏Vue的原型属性
Vue.use(VueAxios, axios)
// 使用vue.use添加vue-cookies
Vue.use(VueCookies)
Vue.config.productionTip = false
Vue.axios.interceptors.request.use(
function (config) {
if (Vue.$cookies.isKey('accessToken')) {
config.headers.Authorization = 'Bearer ' + Vue.$cookies.get('accessToken')
}
return config
},
function (error) {
return Promise.reject(error)
}
)
new Vue({
router,
store,
vuetify,
render: h => h(App)
}).$mount('#app')
至此,在前端使用oauth2已讲解完毕,下一节开始会讲解如何搭建一个用户管理的后台