Authorization
This commit is contained in:
parent
83fc9e6aa8
commit
96e52a14cc
11 changed files with 67 additions and 153 deletions
|
@ -57,7 +57,7 @@ const devWebpackConfig = merge(baseWebpackConfig, {
|
|||
template: 'index.html',
|
||||
inject: true,
|
||||
favicon: resolve('favicon.ico'),
|
||||
title: 'vue-element-admin',
|
||||
title: 'Admin FE',
|
||||
templateParameters: {
|
||||
BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory,
|
||||
},
|
||||
|
|
|
@ -55,7 +55,7 @@ const webpackConfig = merge(baseWebpackConfig, {
|
|||
template: 'index.html',
|
||||
inject: true,
|
||||
favicon: resolve('favicon.ico'),
|
||||
title: 'vue-element-admin',
|
||||
title: 'Admin FE',
|
||||
templateParameters: {
|
||||
BASE_URL: config.build.assetsPublicPath + config.build.assetsSubDirectory,
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = {
|
||||
NODE_ENV: '"development"',
|
||||
ENV_CONFIG: '"dev"',
|
||||
BASE_API: '"https://api-dev"'
|
||||
BASE_API: '"http://localhost:4000"'
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<title>vue-element-admin</title>
|
||||
<title>Admin FE</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src=<%= BASE_URL %>/tinymce4.7.5/tinymce.min.js></script>
|
||||
|
|
|
@ -1,29 +1,42 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export function loginByUsername(username, password) {
|
||||
const data = {
|
||||
username,
|
||||
password
|
||||
}
|
||||
return request({
|
||||
url: '/login/login',
|
||||
export async function loginByUsername(username, password) {
|
||||
const appsRequest = await request({
|
||||
url: '/api/v1/apps',
|
||||
method: 'post',
|
||||
data
|
||||
data: {
|
||||
client_name: `AdminFE_${Math.random()}`,
|
||||
redirect_uris: `${window.location.origin}/oauth-callback`,
|
||||
scopes: 'read write follow'
|
||||
}
|
||||
})
|
||||
|
||||
const app = appsRequest.data
|
||||
|
||||
return request({
|
||||
url: '/oauth/token',
|
||||
method: 'post',
|
||||
data: {
|
||||
client_id: app.client_id,
|
||||
client_secret: app.client_secret,
|
||||
grant_type: 'password',
|
||||
username: username,
|
||||
password: password
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
export function getUserInfo() {
|
||||
return request({
|
||||
url: '/login/logout',
|
||||
url: '/api/account/verify_credentials',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getUserInfo(token) {
|
||||
return request({
|
||||
url: '/user/info',
|
||||
method: 'get',
|
||||
params: { token }
|
||||
})
|
||||
export function logout() {
|
||||
|
||||
}
|
||||
|
||||
const oauth = { loginByUsername, getUserInfo, logout }
|
||||
|
||||
export default oauth
|
||||
|
|
|
@ -63,7 +63,8 @@ export default {
|
|||
theme: 'Theme',
|
||||
clipboardDemo: 'Clipboard',
|
||||
i18n: 'I18n',
|
||||
externalLink: 'External Link'
|
||||
externalLink: 'External Link',
|
||||
users: 'Users'
|
||||
},
|
||||
navbar: {
|
||||
logOut: 'Log Out',
|
||||
|
|
|
@ -26,7 +26,7 @@ router.beforeEach((to, from, next) => {
|
|||
} else {
|
||||
if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
|
||||
store.dispatch('GetUserInfo').then(res => { // 拉取user_info
|
||||
const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop']
|
||||
const roles = res.data.rights.admin ? ['admin'] : []
|
||||
store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
|
||||
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
|
||||
|
|
|
@ -76,32 +76,6 @@ export const constantRouterMap = [
|
|||
meta: { title: 'dashboard', icon: 'dashboard', noCache: true, affix: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/documentation',
|
||||
component: Layout,
|
||||
redirect: '/documentation/index',
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/documentation/index'),
|
||||
name: 'Documentation',
|
||||
meta: { title: 'documentation', icon: 'documentation', affix: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/guide',
|
||||
component: Layout,
|
||||
redirect: '/guide/index',
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/guide/index'),
|
||||
name: 'Guide',
|
||||
meta: { title: 'guide', icon: 'guide', noCache: true }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -112,6 +86,18 @@ export default new Router({
|
|||
})
|
||||
|
||||
export const asyncRouterMap = [
|
||||
{
|
||||
path: '/users',
|
||||
component: Layout,
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/users/index'),
|
||||
name: 'Users',
|
||||
meta: { title: 'users', icon: 'peoples', noCache: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/permission',
|
||||
component: Layout,
|
||||
|
|
|
@ -44,14 +44,13 @@ const user = {
|
|||
},
|
||||
|
||||
actions: {
|
||||
// 用户名登录
|
||||
LoginByUsername({ commit }, userInfo) {
|
||||
const username = userInfo.username.trim()
|
||||
return new Promise((resolve, reject) => {
|
||||
loginByUsername(username, userInfo.password).then(response => {
|
||||
const data = response.data
|
||||
commit('SET_TOKEN', data.token)
|
||||
setToken(response.data.token)
|
||||
commit('SET_TOKEN', data.access_token)
|
||||
setToken(response.data.access_token)
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
|
@ -59,25 +58,25 @@ const user = {
|
|||
})
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
GetUserInfo({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getUserInfo(state.token).then(response => {
|
||||
// 由于mockjs 不支持自定义状态码只能这样hack
|
||||
if (!response.data) {
|
||||
reject('Verification failed, please login again.')
|
||||
}
|
||||
const data = response.data
|
||||
|
||||
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
commit('SET_ROLES', data.roles)
|
||||
if (data.rights) {
|
||||
if (data.rights.admin) {
|
||||
commit('SET_ROLES', ['admin'])
|
||||
}
|
||||
} else {
|
||||
reject('getInfo: roles must be a non-null array!')
|
||||
}
|
||||
|
||||
commit('SET_NAME', data.name)
|
||||
commit('SET_AVATAR', data.avatar)
|
||||
commit('SET_INTRODUCTION', data.introduction)
|
||||
commit('SET_AVATAR', data.profile_image_url)
|
||||
commit('SET_INTRODUCTION', '')
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
|
|
|
@ -12,10 +12,8 @@ const service = axios.create({
|
|||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
// Do something before request is sent
|
||||
if (store.getters.token) {
|
||||
// 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改
|
||||
config.headers['X-Token'] = getToken()
|
||||
config.headers['Authorization'] = `Bearer ${getToken()}`
|
||||
}
|
||||
return config
|
||||
},
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<template>
|
||||
<div class="login-container">
|
||||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
|
||||
<el-form ref="loginForm" :model="loginForm" class="login-form" auto-complete="on" label-position="left">
|
||||
<div class="title-container">
|
||||
<h3 class="title">
|
||||
{{ $t('login.title') }}
|
||||
</h3>
|
||||
<lang-select class="set-language" />
|
||||
</div>
|
||||
|
||||
<el-form-item prop="username">
|
||||
|
@ -41,66 +40,18 @@
|
|||
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">
|
||||
{{ $t('login.logIn') }}
|
||||
</el-button>
|
||||
|
||||
<div style="position:relative">
|
||||
<div class="tips">
|
||||
<span>{{ $t('login.username') }} : admin</span>
|
||||
<span>{{ $t('login.password') }} : {{ $t('login.any') }}</span>
|
||||
</div>
|
||||
<div class="tips">
|
||||
<span style="margin-right:18px;">
|
||||
{{ $t('login.username') }} : editor
|
||||
</span>
|
||||
<span>{{ $t('login.password') }} : {{ $t('login.any') }}</span>
|
||||
</div>
|
||||
|
||||
<el-button class="thirdparty-button" type="primary" @click="showDialog=true">
|
||||
{{ $t('login.thirdparty') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<el-dialog :title="$t('login.thirdparty')" :visible.sync="showDialog">
|
||||
{{ $t('login.thirdpartyTips') }}
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<social-sign />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isvalidUsername } from '@/utils/validate'
|
||||
import LangSelect from '@/components/LangSelect'
|
||||
import SocialSign from './socialsignin'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
components: { LangSelect, SocialSign },
|
||||
data() {
|
||||
const validateUsername = (rule, value, callback) => {
|
||||
if (!isvalidUsername(value)) {
|
||||
callback(new Error('Please enter the correct user name'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validatePassword = (rule, value, callback) => {
|
||||
if (value.length < 6) {
|
||||
callback(new Error('The password can not be less than 6 digits'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
data: function() {
|
||||
return {
|
||||
loginForm: {
|
||||
username: 'admin',
|
||||
password: '1111111'
|
||||
},
|
||||
loginRules: {
|
||||
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
|
||||
password: [{ required: true, trigger: 'blur', validator: validatePassword }]
|
||||
username: '',
|
||||
password: ''
|
||||
},
|
||||
passwordType: 'password',
|
||||
loading: false,
|
||||
|
@ -116,12 +67,6 @@ export default {
|
|||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// window.addEventListener('hashchange', this.afterQRScan)
|
||||
},
|
||||
destroyed() {
|
||||
// window.removeEventListener('hashchange', this.afterQRScan)
|
||||
},
|
||||
methods: {
|
||||
showPwd() {
|
||||
if (this.passwordType === 'password') {
|
||||
|
@ -131,47 +76,19 @@ export default {
|
|||
}
|
||||
},
|
||||
handleLogin() {
|
||||
this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
this.$store.dispatch('LoginByUsername', this.loginForm).then(() => {
|
||||
this.loading = false
|
||||
this.$router.push({ path: this.redirect || '/' })
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
console.log('error submit!!')
|
||||
return false
|
||||
}
|
||||
this.loading = true
|
||||
this.$store.dispatch('LoginByUsername', this.loginForm).then(() => {
|
||||
this.loading = false
|
||||
this.$router.push({ path: this.redirect || '/' })
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
afterQRScan() {
|
||||
// const hash = window.location.hash.slice(1)
|
||||
// const hashObj = getQueryObject(hash)
|
||||
// const originUrl = window.location.origin
|
||||
// history.replaceState({}, '', originUrl)
|
||||
// const codeMap = {
|
||||
// wechat: 'code',
|
||||
// tencent: 'code'
|
||||
// }
|
||||
// const codeName = hashObj[codeMap[this.auth_type]]
|
||||
// if (!codeName) {
|
||||
// alert('第三方登录失败')
|
||||
// } else {
|
||||
// this.$store.dispatch('LoginByThirdparty', codeName).then(() => {
|
||||
// this.$router.push({ path: '/' })
|
||||
// })
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss">
|
||||
/* 修复input 背景不协调 和光标变色 */
|
||||
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
|
||||
|
||||
$bg:#283443;
|
||||
$light_gray:#eee;
|
||||
$cursor: #fff;
|
||||
|
|
Loading…
Reference in a new issue