权限分配这块,其实在之前学习spring时,就已经作为案例练习过了;
不过当时没有整理;最近学习springboot和vue部分这块儿也是可以搭建这个案例
根据权限类型为不同的管理员生成不同的操作菜单
不同的管理员登录到系统后台后,仅能看到自己负责的操作管理菜单,这样的话,简化了管理员的操作,
就在上一篇笔记末尾整合的登录案例上进行------>登录模块
在登录时,会根据账号和密码查询出管理员的信息;查询到信息后;
会将该管理员的Id,账户名,以及管理员类型type存储到token令牌中;
特殊处理后会连同响应信息送到浏览器客户端;
在上篇笔记中已经完成;
用户在第一次登录成功后,会把token令牌的信息以及自己的账号名存储到浏览器的session中’;
注意这个axios请求拦截,他会把浏览器发往服务器的请求拦截,然后为它们的请求头添加 token令牌信息;
管理员表
管理员的列type
:默认为1 ; 0表示超级管理员;1表示普通管理员
角色表
管理员与角色关系表
菜单表
菜单类型:type : 默认为1 ; 0表示系统菜单 ; 1表示业务菜单
菜单角色关系表
前端页面之main.vue组件;
管理员成功登录后就会路由跳转到这个main路径的页面;
<template>
<el-container style="height:100%">
<!-- 上面的一整条导航栏 -->
<el-header style="text-align: right; font-size: 12px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<!-- 右上角个人中心的几个选项-->
<el-dropdown-menu slot="dropdown">
<!-- <el-dropdown-item>修改密码</el-dropdown-item>
<el-dropdown-item>上传头像</el-dropdown-item> -->
<el-dropdown-item @click.native="exit()">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>{{account}}</span>
</el-header>
<el-container>
<!-- 左侧的侧边栏 -->
<el-aside width="200px">
<!-- :default-openeds菜单的默认打开数;这里需要加入路由router -->
<el-menu :default-openeds="['1', '0']" router="">
<el-submenu index="1">
<template slot="title"><i class="el-icon-setting"></i>操作</template>
<el-menu-item-group>
<!-- 这里的文字会绑定上菜单的路径地址,点击即可跳转 -->
<el-menu-item v-bind:index="menu.url" v-for="(menu,index) in menuList" :key="index">{{menu.name}}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!-- 中间的主信息页面 -->
<el-main>
<!-- 这里会显示路由跳转过来的视图-->
<router-view></router-view>
</el-main>
<!-- 底部栏的话本次案例练习暂时不用-->
<!-- <el-footer>Footer</el-footer> -->
</el-container>
</el-container>
</el-container>
</template>
<script>
export default{
data:function(){
return{
//账号名;
account:"",
//菜单列表;
menuList:[],
}
},
methods:{
//安全退出
exit(){
//先给个提示信息;
this.$confirm('您确定退出吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//这里不需要向后端发送请求,清除前端的session即可;
window.sessionStorage.clear();
//跳转到登录页面;
this.$router.push("/login");
})
}
},
//加载页面时就触发
created(){
//从session中取到管理员的账户名; 赋值给数据域的定义模型变量 account
this.account = window.sessionStorage.getItem("account");
//注意this是vue对象;要是直接在请求里面写this的话表示的是axios对象;
var _this = this;
//发出请求,查询该管理员负责的菜单;注意不用带参数,请求头中的token里面就有用户的信息;
this.$http.get("login/findMenuList").then(function(resp){
console.log(resp);
_this.menuList = resp.data.data;
});
}
}
</script>
<style>
.el-header {
background-color: #00FFFF;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #67C23A;
color: #333;
}
.el-main {
background-color: #E9EEF3;
color: #333;
}
</style>
管理员类
/**
* @author by 信计1801班 李智青(小智RE0)
* @date 2021-12-29 14:49
*/
@Data
@Component
public class Admin {
private Integer id;
private String account;
private String password;
private String token;
private String sex;
private String phone;
//角色数组;
private Integer[] roleId;
//旧的,新的文件名;
private String oldFileName;
private String newFileName;
//权限类型;0超管1:普通管理员
private Integer type;
//关联了多个角色;
private List<Role> roleList;
private Date operTime;
}
角色类
/**
* @author by 信计1801班 李智青(小智RE0)
* @date 2021-12-29 15:44
*/
@Component
@Data
public class Role {
//角色ID,姓名,描述;操作人,操作时间;
private Integer id;
private String name;
private String roleDesc;
private Admin admin;
private Date operTime;
//关联多个菜单;
private List<Menu> menuList;
//菜单栏的Id数组;
private Integer[] menuId;
}
菜单类
/**
* @author by 信计1801班 李智青(小智RE0)
* @date 2021-12-29 15:43
*/
@Component
@Data
public class Menu {
//菜单ID,名称,链接;
private Integer id;
private String name;
private String url;
//类型;0系统菜单1业务菜单;
private Integer type;
}
登录的映射文件LoginMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--注意 这里对应空间为持久层映射接口-->
<mapper namespace="com.xiaozhi.backserver.startspringboot.dao.LoginDao">
<select id="loginUser" resultType="admin">
select id,account,type from t_admin where account=#{account} and password=#{password}
</select>
<!--根据权限的不同来获取菜单 类型type:0表示超级管理员负责的系统菜单,1:表示普通管理员负责的业务菜单-->
<select id="findMenuList" resultType="menu">
<choose>
<when test="type==0">
select name, url from t_menu where type =0
</when>
<otherwise>
SELECT
DISTINCT
m.name,m.url
FROM t_admin_role ar LEFT JOIN t_role_menu rm ON rm.role_id=ar.role_id
LEFT JOIN t_menu m ON m.id = rm.menu_id
WHERE ar.admin_id =#{id}
</otherwise>
</choose>
</select>
</mapper>
登录处理的持久层dao
LoginDao
/**
* @author by @CSDN 小智RE0
* @date 2021-12-28 15:55
*/
@Repository
public interface LoginDao {
//根据账号和密码验证用户;
Admin loginUser(Admin admin);
//根据Id查到对应的菜单;
List<Menu> findMenuList(Admin admin);
}
登录处理的服务层service
LoginService
在管理员登录后,进入main主页面时,加载时就发出请求,虽然没有传递参数;
但是在请求头中的token令牌已经存储了该管理员的个人信息,
那么就会通过JWT工具类的方法getTokenInfo(token)
,将token中的信息进行解析,得到查询条件需要的信息(管理员的Id和类型type);
注意在当时对管理员的信息存储到token时,是使用了键值对的形式存入的;
那么这里解析后,也就需要用对应的键获取到信息.
@Transactional
@Service
public class LoginService {
@Autowired
LoginDao loginDao;
//验证用户登录
public Admin loginUser(Admin admin){
return loginDao.loginUser(admin);
}
//根据管理员的Id查询到对应的菜单;
public List<Menu> findMenuList(String token) {
//由token中获取Id和type;
DecodedJWT info = JWTUtil.getTokenInfo(token);
Integer id = info.getClaim("id").asInt();
Integer type = info.getClaim("type").asInt();
Admin admin = new Admin();
admin.setId(id);
admin.setType(type);
return loginDao.findMenuList(admin);
}
}
登录处理的控制层controller
方法
LoginController
/**
* @author by @CSDN 小智RE0
* @date 2021-12-27
*
*/
@RestController
@RequestMapping(value = "/api/login")
public class LoginController {
CommonResult commonResult;
@Autowired
LoginService loginService;
//跨域接收;
//@CrossOrigin("http://localhost:8080/")
@RequestMapping(value = "/login")
public CommonResult login(@RequestBody Admin admin){
try{
System.out.println(admin);
Admin admin1 = loginService.loginUser(admin);
if(admin1!=null){
String token = JWTUtil.token(admin1.getId(), admin1.getAccount(),admin1.getType());
admin1.setToken(token);
commonResult = new CommonResult(200,"正确",admin1);
}else{
commonResult = new CommonResult(201,"账号或密码错误",null);
}
}catch (Exception e){
e.printStackTrace();
commonResult = new CommonResult(500,"服务器错误",null);
}
return commonResult;
}
//查询出该角色对应的菜单;
@GetMapping("/findMenuList")
@ResponseBody
public CommonResult findMenuList(@RequestHeader("token") String token){
try{
List<Menu> menuList = loginService.findMenuList(token);
if(!menuList.isEmpty()){
commonResult = new CommonResult(200,"查询菜单成功",menuList);
}else {
commonResult = new CommonResult(201,"该角色暂无菜单分配",null);
}
}catch (Exception e){
e.printStackTrace();
commonResult = new CommonResult(500,"查询菜单成功",null);
}
return commonResult;
}
}
启动前端和后端服务;
登录admin;超级管理员身份; 菜单就是角色管理和管理员管理
现在这位普通管理员登录后就看到他负责的管理菜单了
若管理员没有负责的菜单,他登录进去后就不会看到操作菜单部分