系列文章目录
《SpringBoot整合SpringSecurity实现权限控制(一):实现原理》
《SpringBoot整合SpringSecurity实现权限控制(二):权限数据基本模型设计》
在上篇文章中我们通过RBAC( Role-Based Access Control:基于角色的访问控制策略)进行权限模型设计,并设计了以下表:
/** * 用户权限 * * @author zhuhuix * @date 2021-08-31 */
@ApiModel(value = "用户权限信息")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PermissionDto {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "路由")
private String path;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "组件路径")
private String component;
@ApiModelProperty(value = "是否隐藏")
private Boolean hidden;
@ApiModelProperty(value = "图标")
private String icon;
@ApiModelProperty(value = "是否缓存")
private Boolean cache;
@ApiModelProperty(value = "重定向")
private String redirect;
@ApiModelProperty(value = "父id")
private Long pId;
}
/** * 用户DAO接口 * * @author zhuhuix * @date 2021-07-19 */
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
/** * 查询用户权限 * @param userId 用户id * @return 权限信息 */
@Select("SELECT m.id, m.`path`, m.`name`, m.`component`, m.`icon`, m.`cache`, m.`hidden`, m.`redirect`, m.p_id " +
"FROM " +
"sys_menu m " +
"INNER JOIN sys_permission p ON p.menu_id = m.id " +
"INNER JOIN sys_user_role ur ON ur.role_id = p.role_id " +
"INNER JOIN sys_user u ON u.id = ur.user_id " +
"INNER JOIN sys_role r ON r.id = ur.role_id where ur.user_id=#{userId}"+
" and m.enabled=1 " +
" order by m.sort "
)
List<PermissionDto> selectUserPermission(Long userId);
}
/** * 用户信息接口 * * @author zhuhuix * @date 2020-04-03 */
public interface SysUserService {
...
/** * 获取用户权限信息 * @param userId 用户id * @return 权限信息 */
List<PermissionDto> getUserPermission(Long userId);
}
/** * 用户接口实现类 * * @author zhuhuix * @date 2020-04-03 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SysUserServiceImpl implements SysUserService {
private final SysUserMapper sysUserMapper;
private final UploadFileTool uploadFileTool;
...
@Override
public List<PermissionDto> getUserPermission(Long userId) {
return sysUserMapper.selectUserPermission(userId);
}
}
/** * api用户信息 * * @author zhuhuix * @date 2021-08-16 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/api/user")
@Api(tags = "用户信息接口")
public class SysUserController {
private final SysUserService sysUserService;
...
@ApiOperation("获取用户权限")
@GetMapping("/permission/{userId}")
public ResponseEntity<Object> getUserPermission(@PathVariable Long userId) {
return ResponseEntity.ok(sysUserService.getUserPermission(userId));
}
}
import request from '@/utils/request'
...
// 获取用户权限
export function getUserPermission(userId) {
return request({
url: '/api/user/permission/' + userId,
method: 'get'
})
}
import { constantRoutes, router } from '@/router'
import { getUserPermission } from '@/api/user'
import store from '@/store'
import Layout from '@/layout/index'
// 处理路由
export const filterAsyncRouter = (routers) => { // 遍历后台传来的路由字符串,转换为组件对象
return routers.filter(router => {
if (router.component) {
if (router.component === 'Layout') { // Layout组件特殊处理
router.component = Layout
} else {
const component = router.component
router.component = loadView(component)
}
}
router.meta = { title: router.name, icon: router.icon, noCache: !router.cache }
if (router.children && router.children.length) {
router.children = filterAsyncRouter(router.children)
}
return true
})
}
export const loadView = (view) => {
return (resolve) => require([`@/views/${view}`], resolve)
}
const state = {
routes: [],
addRoutes: [],
menuLoaded: false
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
console.log('routes', state.routes)
// 增加动态路由
router.addRoutes(routes)
},
SET_MENULOADED: (state, menuLoaded) => {
state.menuLoaded = menuLoaded
}
}
const actions = {
generateRoutes({ commit }) {
return new Promise(resolve => {
let accessedRoutes
getUserPermission(store.getters.user.id).then(res => {
accessedRoutes = ArrayToTreeData(res)
if (accessedRoutes && accessedRoutes.length) {
const asyncRouter = filterAsyncRouter(accessedRoutes)
asyncRouter.push({ path: '*', redirect: '/404', hidden: true })
commit('SET_ROUTES', asyncRouter)
commit('SET_MENULOADED', true)
resolve(asyncRouter)
}
})
})
},
setMenuLoaded({ commit }, munuLoaded) {
return new Promise(resolve => {
commit('SET_MENULOADED', munuLoaded)
})
}
}
function ArrayToTreeData(data) {
const cloneData = JSON.parse(JSON.stringify(data)) // 对源数据深度克隆
return cloneData.filter(father => {
const branchArr = cloneData.filter(child => father.id === child.pid) // 返回每一项的子级数组
branchArr.length > 0 ? father.children = branchArr : '' // 如果存在子级,则给父级添加一个children属性,并赋值
return father.pid === null // 返回第一层
})
}
export default {
namespaced: true,
state,
mutations,
actions
}
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login', '/register'] // no redirect whitelist
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
try {
// 首次登录需要获取用户信息
store.dispatch('getInfo').then(() => {
// 根据用户信息获取用户权限并动态加载菜单
store.dispatch('permission/generateRoutes').then(() => next({ ...to, replace: true }))
})
} catch (error) {
store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
} else {
// 如果菜单未装载过,则需要重新
if (!store.getters.menuLoaded) {
store.dispatch('permission/generateRoutes').then(() => next())
} else {
next()
}
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
router.afterEach(() => {
// finish progress bar
NProgress.done()
})
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://zhuhuix.blog.csdn.net/article/details/119991687
内容来源于网络,如有侵权,请联系作者删除!