diff --git a/oms_web/oms_vue/src/api/login.js b/oms_web/oms_vue/src/api/login.js
index 7b7388fd..186420d9 100644
--- a/oms_web/oms_vue/src/api/login.js
+++ b/oms_web/oms_vue/src/api/login.js
@@ -1,21 +1,21 @@
import request from '@/utils/request'
-// 登录方法
-export function login(username, password, code, uuid) {
- const data = {
- username,
- password,
- code,
- uuid
- }
+// 登录方法 - 基于 Session 认证,使用 FormData 格式
+export function login(username, password, code, rememberMe) {
+ const formData = new FormData()
+ formData.append('username', username)
+ formData.append('password', password)
+ formData.append('validateCode', code)
+ formData.append('rememberMe', rememberMe || false)
return request({
url: '/login',
headers: {
isToken: false,
+ 'Content-Type': 'multipart/form-data',
repeatSubmit: false
},
method: 'post',
- data: data
+ data: formData
})
}
@@ -39,22 +39,10 @@ export function getInfo() {
})
}
-// 退出方法
+// 退出方法 - 基于 Session 认证
export function logout() {
return request({
url: '/logout',
method: 'post'
})
}
-
-// 获取验证码
-export function getCodeImg() {
- return request({
- url: '/captchaImage',
- headers: {
- isToken: false
- },
- method: 'get',
- timeout: 20000
- })
-}
\ No newline at end of file
diff --git a/oms_web/oms_vue/src/permission.js b/oms_web/oms_vue/src/permission.js
index b66190b3..480e0445 100644
--- a/oms_web/oms_vue/src/permission.js
+++ b/oms_web/oms_vue/src/permission.js
@@ -3,7 +3,6 @@ import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
-import { getToken } from '@/utils/auth'
import { isPathMatch } from '@/utils/validate'
import { isRelogin } from '@/utils/request'
@@ -17,43 +16,37 @@ const isWhiteList = (path) => {
router.beforeEach((to, from, next) => {
NProgress.start()
- if (getToken()) {
- to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
- /* has token*/
- if (to.path === '/login') {
- next({ path: '/' })
- NProgress.done()
- } else if (isWhiteList(to.path)) {
- next()
- } else {
- if (store.getters.roles.length === 0) {
- isRelogin.show = true
- // 判断当前用户是否已拉取完user_info信息
- store.dispatch('GetInfo').then(() => {
- isRelogin.show = false
- store.dispatch('GenerateRoutes').then(accessRoutes => {
- // 根据roles权限生成可访问的路由表
- router.addRoutes(accessRoutes) // 动态添加可访问路由表
- next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
- })
- }).catch(err => {
- store.dispatch('LogOut').then(() => {
- Message.error(err)
- next({ path: '/' })
- })
- })
- } else {
- next()
- }
- }
+ // 基于 Session 认证:通过是否有角色信息来判断登录状态
+ const hasRoles = store.getters.roles && store.getters.roles.length > 0
+
+ to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
+
+ if (isWhiteList(to.path)) {
+ // 在免登录白名单,直接进入
+ next()
+ NProgress.done()
} else {
- // 没有token
- if (isWhiteList(to.path)) {
- // 在免登录白名单,直接进入
+ if (hasRoles) {
+ // 已有用户信息,放行
next()
} else {
- next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页
- NProgress.done()
+ // 没有用户信息,尝试获取
+ isRelogin.show = true
+ store.dispatch('GetInfo').then(() => {
+ isRelogin.show = false
+ store.dispatch('GenerateRoutes').then(accessRoutes => {
+ // 根据roles权限生成可访问的路由表
+ router.addRoutes(accessRoutes) // 动态添加可访问路由表
+ next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
+ })
+ }).catch(err => {
+ // 获取用户信息失败,说明未登录或 Session 已过期
+ store.dispatch('FedLogOut').then(() => {
+ Message.error(err || '未登录或登录超时,请重新登录')
+ next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
+ NProgress.done()
+ })
+ })
}
}
})
diff --git a/oms_web/oms_vue/src/store/modules/user.js b/oms_web/oms_vue/src/store/modules/user.js
index 6a7b710a..fb1ff782 100644
--- a/oms_web/oms_vue/src/store/modules/user.js
+++ b/oms_web/oms_vue/src/store/modules/user.js
@@ -1,13 +1,11 @@
import router from '@/router'
import { MessageBox, } from 'element-ui'
import { login, logout, getInfo } from '@/api/login'
-import { getToken, setToken, removeToken } from '@/utils/auth'
import { isHttp, isEmpty } from "@/utils/validate"
import defAva from '@/assets/images/profile.jpg'
const user = {
state: {
- token: getToken(),
id: '',
name: '',
nickName: '',
@@ -17,9 +15,6 @@ const user = {
},
mutations: {
- SET_TOKEN: (state, token) => {
- state.token = token
- },
SET_ID: (state, id) => {
state.id = id
},
@@ -41,16 +36,14 @@ const user = {
},
actions: {
- // 登录
+ // 登录 - 基于 Session 认证,不需要保存 token
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
- const uuid = userInfo.uuid
+ const rememberMe = userInfo.rememberMe
return new Promise((resolve, reject) => {
- login(username, password, code, uuid).then(res => {
- setToken(res.token)
- commit('SET_TOKEN', res.token)
+ login(username, password, code, rememberMe).then(res => {
resolve()
}).catch(error => {
reject(error)
@@ -62,14 +55,16 @@ const user = {
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
- const user = res.user
+ // 后端返回的数据在 res.data 中
+ const data = res.data || res
+ const user = data.user
let avatar = user.avatar || ""
if (!isHttp(avatar)) {
avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
}
- if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
- commit('SET_ROLES', res.roles)
- commit('SET_PERMISSIONS', res.permissions)
+ if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
+ commit('SET_ROLES', data.roles)
+ commit('SET_PERMISSIONS', data.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
@@ -78,13 +73,13 @@ const user = {
commit('SET_NICK_NAME', user.nickName)
commit('SET_AVATAR', avatar)
/* 初始密码提示 */
- if(res.isDefaultModifyPwd) {
+ if(data.isDefaultModifyPwd) {
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
}).catch(() => {})
}
/* 过期密码提示 */
- if(!res.isDefaultModifyPwd && res.isPasswordExpired) {
+ if(!data.isDefaultModifyPwd && data.isPasswordExpired) {
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
}).catch(() => {})
@@ -96,14 +91,12 @@ const user = {
})
},
- // 退出系统
+ // 退出系统 - 基于 Session 认证
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
- logout(state.token).then(() => {
- commit('SET_TOKEN', '')
+ logout().then(() => {
commit('SET_ROLES', [])
commit('SET_PERMISSIONS', [])
- removeToken()
resolve()
}).catch(error => {
reject(error)
@@ -111,11 +104,11 @@ const user = {
})
},
- // 前端 登出
+ // 前端 登出 - 清除状态
FedLogOut({ commit }) {
return new Promise(resolve => {
- commit('SET_TOKEN', '')
- removeToken()
+ commit('SET_ROLES', [])
+ commit('SET_PERMISSIONS', [])
resolve()
})
}
diff --git a/oms_web/oms_vue/src/utils/request.js b/oms_web/oms_vue/src/utils/request.js
index 7150ecb1..34ee6390 100644
--- a/oms_web/oms_vue/src/utils/request.js
+++ b/oms_web/oms_vue/src/utils/request.js
@@ -1,7 +1,6 @@
import axios from 'axios'
import { Notification, MessageBox, Message, Loading } from 'element-ui'
import store from '@/store'
-import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from "@/utils/ruoyi"
import cache from '@/plugins/cache'
@@ -17,18 +16,17 @@ const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
- timeout: 10000
+ timeout: 10000,
+ // 允许携带cookie(Session认证必需)
+ withCredentials: true
})
// request拦截器
service.interceptors.request.use(config => {
- // 是否需要设置 token
- const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
- if (getToken() && !isToken) {
- config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
- }
+ config.headers['X-Requested-With'] = 'H5'
+ // Session 认证依赖 Cookie,无需手动设置 token
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params)
@@ -39,7 +37,7 @@ service.interceptors.request.use(config => {
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
- data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
+ data: (typeof config.data === 'object' && !(config.data instanceof FormData)) ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小
@@ -79,7 +77,7 @@ service.interceptors.response.use(res => {
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
- return res.data
+ return res
}
if (code === 401) {
if (!isRelogin.show) {
diff --git a/oms_web/oms_vue/src/views/login.vue b/oms_web/oms_vue/src/views/login.vue
index 5bdda11c..381f6dac 100644
--- a/oms_web/oms_vue/src/views/login.vue
+++ b/oms_web/oms_vue/src/views/login.vue
@@ -62,7 +62,6 @@
\ No newline at end of file
+
diff --git a/oms_web/oms_vue/vue.config.js b/oms_web/oms_vue/vue.config.js
index 40e140d5..66d5cb64 100644
--- a/oms_web/oms_vue/vue.config.js
+++ b/oms_web/oms_vue/vue.config.js
@@ -9,7 +9,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
-const baseUrl = 'http://localhost:8080' // 后端接口
+const baseUrl = 'http://localhost:28080' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口
@@ -38,6 +38,10 @@ module.exports = {
[process.env.VUE_APP_BASE_API]: {
target: baseUrl,
changeOrigin: true,
+ // Session 认证需要携带 Cookie
+ cookieDomainRewrite: {
+ '*': ''
+ },
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java
index 230cc3b2..2d3b8128 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysCaptchaController.java
@@ -8,6 +8,8 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+
+import com.ruoyi.common.utils.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -48,6 +50,7 @@ public class SysCaptchaController extends BaseController
response.setContentType("image/jpeg");
String type = request.getParameter("type");
+ type = StringUtils.isEmpty(type) ? "math" : type;
String capStr = null;
String code = null;
BufferedImage bi = null;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
index 0a43e3bc..6930db21 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
@@ -155,4 +155,11 @@ public class SysConfigController extends BaseController
{
return configService.checkConfigKeyUnique(config);
}
+ @GetMapping("/configKey/{key}")
+ @ResponseBody
+ public AjaxResult queryKey(@PathVariable("key") String key)
+ {
+ return success(configService.selectConfigByKey(key));
+ }
+
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
index 770766fd..ab4d1de9 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
@@ -1,6 +1,10 @@
package com.ruoyi.web.controller.system;
+import java.util.ArrayList;
import java.util.List;
+
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysDictTypeService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@@ -33,7 +37,8 @@ public class SysDictDataController extends BaseController
@Autowired
private ISysDictDataService dictDataService;
-
+ @Autowired
+ private ISysDictTypeService dictTypeService;
@RequiresPermissions("system:dict:view")
@GetMapping()
public String dictData()
@@ -72,6 +77,22 @@ public class SysDictDataController extends BaseController
mmap.put("dictType", dictType);
return prefix + "/add";
}
+ /**
+ * 新增字典类型
+ */
+
+ @GetMapping("/type/{dictType}")
+ @ResponseBody
+ public AjaxResult add(@PathVariable("dictType") String dictType)
+ {
+
+ List data = dictTypeService.selectDictDataByType(dictType);
+ if (StringUtils.isNull(data))
+ {
+ data = new ArrayList();
+ }
+ return success(data);
+ }
/**
* 新增保存字典类型
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
index 5fe06998..d16e66d3 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
@@ -1,21 +1,11 @@
package com.ruoyi.web.controller.system;
-import java.util.Date;
-import java.util.List;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.CookieUtils;
@@ -25,6 +15,18 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysMenuService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* 首页 业务处理
@@ -39,7 +41,6 @@ public class SysIndexController extends BaseController
@Autowired
private ISysConfigService configService;
-
@Autowired
private SysPasswordService passwordService;
@GetMapping("/test")
@@ -178,4 +179,164 @@ public class SysIndexController extends BaseController
}
return false;
}
+
+ /**
+ * 获取用户信息(供前后端分离的前端调用)
+ *
+ * @return 用户信息、角色、权限
+ */
+ @GetMapping("/getInfo")
+ @ResponseBody
+ public AjaxResult getInfo()
+ {
+ SysUser user = getSysUser();
+ if (StringUtils.isNull(user))
+ {
+ return AjaxResult.error("未登录或登录超时");
+ }
+ // 角色集合
+ Set roles = user.getRoles().stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
+ // 权限集合
+ Set permissions = menuService.selectPermsByUserId(user.getUserId());
+
+ Map data = new HashMap<>();
+ data.put("user", user);
+ data.put("roles", roles);
+ data.put("permissions", permissions);
+ data.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
+ data.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
+
+ return AjaxResult.success(data);
+ }
+
+ /**
+ * 获取路由信息(供前后端分离的前端调用)
+ *
+ * @return 路由信息
+ */
+ @GetMapping("/getRouters")
+ @ResponseBody
+ public AjaxResult getRouters()
+ {
+ SysUser user = getSysUser();
+ if (StringUtils.isNull(user))
+ {
+ return AjaxResult.error("未登录或登录超时");
+ }
+
+ List menus = menuService.selectMenusByUser(user);
+ List