当前位置:   article > 正文

springboot+vue+springsecurity前后端权限管理系统_springboot + springboot - security 用户管理

springboot + springboot - security 用户管理

由于字数限制,请阅读原文,原文附源码和sql以及项目演示地址和项目资料。

环境:

win10、idea22023.2、vscode1.7、maven3.5、jdk8、Redis

技术:

  • springboot2.5.9

  • springsecurity

  • Redis

  • mybatis plus

  • mysql5.7.38

  • swagger

  • jwt

  • vue2

  • element ui

  • vuex

  • vue-router

  • axios

  • mockjs

  • echarts

  • less

模块:

  1. 登录页面

  2. 首页

  3. 权限管理

    1.用户管理

    2.角色管理

    3.菜单管理

功能要点:

  1. 从0到1实现项目前后端搭建

  2. vuex实现面包屑和Tag功能

  3. vuex+localStorage动态路由和菜单(重点)

  4. 封装一个ECharts组件

  5. 封装Table表格

  6. 树形表格和CheckBox的使用

  7. 封装统一返回类

  8. 两种方式实现代码生成,解放双手

  9. jwt、swagger、Redis封装

  10. 权限管理(重点)

项目截图

1、登录页面

d906325f5d7942401a06d8708517e85a.png

2、首页

3210e95481c9812f41fa647b07c48555.png

3、用户管理

c8f8ec1c6c509c9b4853818304530bea.png

4、角色管理

cc103c9863b97a10a64cf8f17cf4fb60.png

5、分配权限

34958a307f40a99bbcb655337eacdcc0.png

6、菜单管理

3d2ce369feeba22966c3a26d5747871d.png

7、根据权限动态加载菜单和按钮

e631043bc330c156d8fbc681c0a6455f.png

8、部分主要代码

登录

  1. <template>
  2. <el-form
  3. ref="form"
  4. label-width="70px"
  5. :inline="true"
  6. class="login-container"
  7. :model="form"
  8. :rules="rules"
  9. >
  10. <h3 class="login_title">系统登录</h3>
  11. <el-form-item label="用户名" prop="username">
  12. <el-input v-model="form.username" placeholder="请输入账号"></el-input>
  13. </el-form-item>
  14. <el-form-item label="密码" prop="password">
  15. <el-input
  16. type="password"
  17. v-model="form.password"
  18. placeholder="请输入密码"
  19. ></el-input>
  20. </el-form-item>
  21. <el-form-item label="验证码" prop="code">
  22. <el-input v-model="form.code" maxlength="6"></el-input>
  23. </el-form-item>
  24. <el-form-item>
  25. <el-image
  26. :src="captchaImg"
  27. class="captchaImg"
  28. style="margin-left: 15px"
  29. @click="getCaptcha"
  30. ></el-image>
  31. </el-form-item>
  32. <el-form-item>
  33. <el-button
  34. @click="submit"
  35. style="margin-left: 105px; margin-top: 10px"
  36. type="primary"
  37. :loading="loading"
  38. >登录</el-button
  39. >
  40. <!-- <el-button
  41. @click="submit1"
  42. style="margin-left: 105px; margin-top: 10px"
  43. type="primary"
  44. :loading="loading"
  45. >登录1</el-button
  46. > -->
  47. </el-form-item>
  48. </el-form>
  49. </template>
  50. <script>
  51. // import Mock from 'mockjs'
  52. // import Cookie from 'js-cookie'
  53. // import { getMenu } from '../api'
  54. import qs from "qs";
  55. import http from "@/utils/request";
  56. export default {
  57. data() {
  58. return {
  59. captchaImg: "",
  60. loading: false,
  61. form: {
  62. username: "admin",
  63. password: "111111",
  64. token: "aaaaa",
  65. code: "",
  66. },
  67. rules: {
  68. username: [
  69. { required: true, trigger: "blur", message: "请输入用户名" },
  70. ],
  71. password: [{ required: true, trigger: "blur", message: "请输入密码" }],
  72. },
  73. };
  74. },
  75. created() {
  76. this.getCaptcha();
  77. },
  78. methods: {
  79. submit1() {},
  80. getCaptcha() {
  81. http.get("/captcha").then((res) => {
  82. if(res.code === 20000){
  83. console.log("/captcha");
  84. console.log(res);
  85. this.form.token = res.data.data.token;
  86. this.captchaImg = res.data.data.captchaImg;
  87. //this.form.code = "";
  88. }
  89. });
  90. },
  91. // 登录
  92. submit() {
  93. let that = this;
  94. that.$refs.form.validate((valid) => {
  95. if (valid) {
  96. this.loading = true;
  97. this.$store
  98. .dispatch("Login", this.form)
  99. .then((res) => {
  100. if (res.code != 20000) {
  101. that.$message({
  102. type: "warning",
  103. message: res.message,
  104. });
  105. this.loading = false;
  106. return false;
  107. }
  108. this.loading = false;
  109. this.$router.push({ path: "/home" });
  110. })
  111. .catch(() => {
  112. this.loading = false;
  113. });
  114. // http
  115. // .post("/login?" + qs.stringify(this.form))
  116. // .then((res) => {
  117. // if (res.code != 20000) {
  118. // that.$message({
  119. // type: "warning",
  120. // message: res.message,
  121. // });
  122. // }
  123. // console.log(res);
  124. // const jwt = res.data.authorization;
  125. // this.$store.commit("SET_TOKEN", jwt);
  126. // //
  127. // this.$router.push("/home");
  128. // })
  129. // .catch((e) => {});
  130. //this.loading = true;
  131. // that.$store
  132. // .dispatch("Login", that.form)
  133. // .then(() => {
  134. // //this.loading = false;
  135. // that.$router.push({ path: "/" });
  136. // })
  137. // .catch(() => {
  138. // //this.loading = false;
  139. // });
  140. } else {
  141. console.log("error submit!!");
  142. return false;
  143. }
  144. });
  145. // // token信息
  146. // const token = Mock.Random.guid()
  147. // 校验通过
  148. // this.$refs.form.validate((valid) => {
  149. // if (valid) {
  150. // getMenu(this.form).then(({ data }) => {
  151. // console.log(data)
  152. // if (data.code === 20000) {
  153. // // token信息存入cookie用于不同页面间的通信
  154. // Cookie.set('token', data.data.token)
  155. // // 获取菜单的数据,存入store中
  156. // this.$store.commit('setMenu', data.data.menu)
  157. // this.$store.commit('addMenu', this.$router)
  158. // // 跳转到首页
  159. // this.$router.push('/home')
  160. // } else {
  161. // this.$message.error(data.data.message);
  162. // }
  163. // })
  164. // }
  165. // })
  166. },
  167. },
  168. };
  169. </script>
  170. <style lang="less" scoped>
  171. .login-container {
  172. width: 650px;
  173. border: 1px solid #eaeaea;
  174. margin: 180px auto;
  175. padding: 35px 35px 15px 35px;
  176. background-color: #fff;
  177. border-radius: 15px;
  178. box-shadow: 0 0 25px #cac6c6;
  179. box-sizing: border-box;
  180. .login_title {
  181. text-align: center;
  182. margin-bottom: 40px;
  183. color: #505458;
  184. }
  185. .el-input {
  186. width: 198px;
  187. }
  188. }
  189. </style>

菜单

  1. <template>
  2. <div>
  3. <el-table
  4. :data="tableData"
  5. style="width: 100%; margin-bottom: 20px"
  6. row-key="id"
  7. border
  8. default-expand-all
  9. :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
  10. >
  11. <el-table-column prop="name" label="名称" sortable min-width="20%">
  12. </el-table-column>
  13. <el-table-column prop="path" label="访问路径" sortable min-width="15%">
  14. </el-table-column>
  15. <el-table-column
  16. prop="component"
  17. label="组件路径"
  18. sortable
  19. min-width="15%"
  20. >
  21. </el-table-column>
  22. <el-table-column
  23. prop="permissionValue"
  24. label="权限值"
  25. sortable
  26. min-width="15%"
  27. >
  28. </el-table-column>
  29. <el-table-column prop="status" label="状态" sortable min-width="10%">
  30. </el-table-column>
  31. <el-table-column prop="icon" label="图标" sortable min-width="10%">
  32. </el-table-column>
  33. <el-table-column label="操作" min-width="15%">
  34. <template slot-scope="scope">
  35. <!-- 第一层和第二层可以添加菜单,第三层添加功能,第四层修改功能 -->
  36. <el-button
  37. v-if="scope.row.level === 1 || scope.row.level === 2"
  38. type="text"
  39. size="mini"
  40. @click="addOrEditMenuDialog(scope.row, 'add')"
  41. >添加菜单</el-button
  42. >
  43. <el-button
  44. v-if="scope.row.level === 3"
  45. type="text"
  46. size="mini"
  47. @click="
  48. () => {
  49. dialogPermissionFormVisible = true;
  50. permissionForm = { ...PERMISSION_FORM };
  51. permissionForm.pid = scope.row.id;
  52. permissionTitle = '添加功能';
  53. }
  54. "
  55. >
  56. 添加功能</el-button
  57. >
  58. <el-button
  59. v-if="scope.row.level === 4"
  60. type="text"
  61. size="mini"
  62. @click="updatePermissionDialog(scope.row)"
  63. >修改功能</el-button
  64. >
  65. <el-button
  66. v-if="scope.row.level !== 1 && scope.row.level !== 4"
  67. type="text"
  68. size="mini"
  69. @click="addOrEditMenuDialog(scope.row, 'edit')"
  70. >修改</el-button
  71. >
  72. <el-button
  73. v-if="scope.row.level !== 1"
  74. @click="deleteSubmit(scope.row)"
  75. type="text"
  76. size="mini"
  77. >删除</el-button
  78. >
  79. </template>
  80. </el-table-column>
  81. </el-table>
  82. <!-- 添加菜单的窗口 -->
  83. <el-dialog
  84. :title="title"
  85. :label-position="labelPosition"
  86. :visible.sync="dialogFormVisible"
  87. >
  88. <el-form
  89. ref="menuForm"
  90. :model="menuForm"
  91. :rules="menuFormRules"
  92. label-width="120px"
  93. >
  94. <el-form-item label="菜单名称" prop="name">
  95. <el-input v-model="menuForm.name"></el-input>
  96. </el-form-item>
  97. <el-form-item label="访问路径" prop="path" v-if="showFlag">
  98. <el-input v-model="menuForm.path"></el-input>
  99. </el-form-item>
  100. <el-form-item label="组件路径" prop="component" v-if="showFlag">
  101. <el-input v-model="menuForm.component"></el-input>
  102. </el-form-item>
  103. <!-- <el-form-item label="权限值" prop="permissionValue">
  104. <el-input v-model="menuForm.permissionValue"></el-input>
  105. </el-form-item> -->
  106. <el-form-item label="图标" prop="icon">
  107. <el-input v-model="menuForm.icon"></el-input>
  108. </el-form-item>
  109. </el-form>
  110. <div slot="footer" class="dialog-footer">
  111. <el-button @click="resetMenu()">取 消</el-button>
  112. <el-button type="primary" @click="addMenuFormSubmit()">确 定</el-button>
  113. </div>
  114. </el-dialog>
  115. <!-- 添加功能的窗口 -->
  116. <el-dialog
  117. :title="permissionTitle"
  118. :label-position="labelPosition"
  119. :visible.sync="dialogPermissionFormVisible"
  120. >
  121. <el-form
  122. ref="permissionForm"
  123. :model="permissionForm"
  124. :rules="permissionFormRules"
  125. label-width="120px"
  126. >
  127. <el-form-item label="功能名称" prop="name">
  128. <el-input v-model="permissionForm.name"></el-input>
  129. </el-form-item>
  130. <el-form-item label="访问路径" prop="path">
  131. <el-input v-model="permissionForm.path"></el-input>
  132. </el-form-item>
  133. <el-form-item label="组件路径" prop="component">
  134. <el-input v-model="permissionForm.component"></el-input>
  135. </el-form-item>
  136. <el-form-item label="功能权限值" prop="permissionValue">
  137. <el-input v-model="permissionForm.permissionValue"></el-input>
  138. </el-form-item>
  139. <el-form-item label="图标" prop="icon">
  140. <el-input v-model="permissionForm.icon"></el-input>
  141. </el-form-item>
  142. </el-form>
  143. <div slot="footer" class="dialog-footer">
  144. <el-button @click="resetPermission()">取 消</el-button>
  145. <el-button type="primary" @click="addPermissonFormSubmit()"
  146. >确 定</el-button
  147. >
  148. </div>
  149. </el-dialog>
  150. </div>
  151. </template>
  152. <script>
  153. import { getData, updateMenuSubmit, deleteSubmit } from "@/api/permission.js";
  154. import http from "@/utils/request";
  155. const MENU_FORM = {
  156. name: "",
  157. path: "",
  158. component: "",
  159. // status: 0,
  160. icon: "setting",
  161. pid: 0,
  162. type: "1",
  163. id: "",
  164. };
  165. const PERMISSION_FORM = {
  166. name: "",
  167. path: "",
  168. component: "",
  169. permissionValue: "",
  170. // status: 0,
  171. icon: "setting",
  172. pid: 0,
  173. type: "2",
  174. id: "",
  175. };
  176. export default {
  177. data() {
  178. return {
  179. showFlag: true,
  180. labelPosition: "left",
  181. tableData: [], //获取递归取得的全部菜单
  182. dialogFormVisible: false, //添加修改菜单窗口开关
  183. dialogPermissionFormVisible: false, //添加修改功能窗口开关
  184. title: "添加菜单", //添加修改菜单标题
  185. permissionTitle: "添加功能", //添加修改菜单标题
  186. menuForm: MENU_FORM, //添加修改菜单内容
  187. permissionForm: PERMISSION_FORM, //添加修改功能内容
  188. //表单验证
  189. menuFormRules: {
  190. name: [
  191. { required: true, message: "请输入菜单名称", trigger: "blur" },
  192. {
  193. min: 3,
  194. max: 30,
  195. message: "长度在 3 到 30 个字符",
  196. trigger: "blur",
  197. },
  198. ],
  199. path: [
  200. { message: "请输入访问路径", trigger: "blur" },
  201. {
  202. min: 3,
  203. max: 18,
  204. message: "长度在 3 到 18 个字符",
  205. trigger: "blur",
  206. },
  207. ],
  208. component: [
  209. { message: "请输入组件路径", trigger: "blur" },
  210. {
  211. min: 3,
  212. max: 18,
  213. message: "长度在 3 到 18 个字符",
  214. trigger: "blur",
  215. },
  216. ],
  217. },
  218. //功能表单验证
  219. permissionFormRules: {
  220. name: [
  221. { required: true, message: "请输入菜单名称", trigger: "blur" },
  222. { min: 3, max: 8, message: "长度在 3 到 8 个字符", trigger: "blur" },
  223. ],
  224. permissionValue: [
  225. { required: true, message: "请输入权限值", trigger: "blur" },
  226. {
  227. min: 3,
  228. max: 18,
  229. message: "长度在 3 到 18 个字符",
  230. trigger: "blur",
  231. },
  232. ],
  233. },
  234. };
  235. },
  236. created() {
  237. //获取递归取得的全部菜单
  238. this.getAllMenuList();
  239. },
  240. methods: {
  241. //修改功能
  242. updatePermissionDialog(val) {
  243. this.dialogPermissionFormVisible = true;
  244. this.permissionForm = val;
  245. this.permissionTitle = "修改功能";
  246. },
  247. //取消菜单添加或修改
  248. resetMenu() {
  249. this.dialogFormVisible = false;
  250. this.menuForm = {};
  251. },
  252. //取消功能添加或修改
  253. resetPermission() {
  254. this.dialogPermissionFormVisible = false;
  255. this.permissionForm = {};
  256. },
  257. //添加修改下级功能
  258. addPermissonFormSubmit() {
  259. let that = this;
  260. this.$refs.permissionForm.validate((valid) => {
  261. if (valid) {
  262. if (that.permissionForm.id) {
  263. //修改
  264. updateMenuSubmit(that.permissionForm).then((res) => {
  265. if (res.code === 20000) {
  266. that.$message({
  267. type: "success",
  268. message: "修改功能成功",
  269. });
  270. //刷新页面
  271. that.getAllMenuList();
  272. that.dialogPermissionFormVisible = false;
  273. that.permissionForm = { ...PERMISSION_FORM };
  274. }
  275. });
  276. } else {
  277. //新增
  278. //let permission = that.menuForm;
  279. http({
  280. url: "/permission/save",
  281. method: "post",
  282. data: that.permissionForm,
  283. }).then((res) => {
  284. if (res.code === 20000) {
  285. that.$message({
  286. type: "success",
  287. message: "添加功能成功",
  288. });
  289. //刷新页面
  290. that.getAllMenuList();
  291. that.dialogPermissionFormVisible = false;
  292. that.permissionForm = { ...PERMISSION_FORM };
  293. }
  294. });
  295. }
  296. } else {
  297. return false;
  298. }
  299. });
  300. },
  301. //删除
  302. deleteSubmit(val) {
  303. let that = this;
  304. this.$confirm("此操作将永久删除该记录,是否继续?", "提升", {
  305. distinguishCancelAndClose: true,
  306. confirmButtonText: "确定",
  307. cancelButtonText: "取消",
  308. })
  309. .then(() => {
  310. deleteSubmit(val.id).then((res) => {
  311. if (res.code === 20000) {
  312. that.$message({
  313. type: "success",
  314. message: "删除成功",
  315. });
  316. //刷新页面
  317. that.getAllMenuList();
  318. }
  319. });
  320. this.$message({
  321. type: "info",
  322. message: "保存修改",
  323. });
  324. })
  325. .catch((action) => {
  326. this.$message({
  327. type: "info",
  328. message:
  329. action === "cancel" ? "放弃保存并离开页面" : "停留在当前页面",
  330. });
  331. });
  332. // let that = this;
  333. // this.$confirm("此操作将永久删除该记录,是否继续?", "提升", {
  334. // cofirmButtonText: "确定",
  335. // cancelButtonText: "取消",
  336. // type: "warning",
  337. // }).then(() => {
  338. // deleteSubmit(val.id).then((res) => {
  339. // if (res.code === 20000) {
  340. // that.$message({
  341. // type: "success",
  342. // message: "删除成功",
  343. // });
  344. // //刷新页面
  345. // that.getAllMenuList();
  346. // }
  347. // });
  348. // });
  349. },
  350. //修改
  351. updateMenuSubmit() {
  352. let that = this;
  353. updateMenuSubmit(that.menuForm).then((res) => {
  354. if (res.code === 20000) {
  355. that.$message({
  356. type: "success",
  357. message: "修改菜单成功",
  358. });
  359. //刷新页面
  360. that.getAllMenuList();
  361. that.dialogFormVisible = false;
  362. }
  363. });
  364. },
  365. //新增
  366. addMenuSubmit() {
  367. let that = this;
  368. //let permission = that.menuForm;
  369. http({
  370. url: "/admin/sys/permission/save",
  371. method: "post",
  372. data: that.menuForm,
  373. }).then((res) => {
  374. if (res.code === 20000) {
  375. that.$message({
  376. type: "success",
  377. message: "添加菜单成功",
  378. });
  379. //刷新页面
  380. that.getAllMenuList();
  381. that.dialogFormVisible = false;
  382. }
  383. });
  384. },
  385. //提交添加菜单的数据
  386. addMenuFormSubmit() {
  387. let that = this;
  388. this.$refs.menuForm.validate((valid) => {
  389. if (valid) {
  390. if (that.menuForm.id) {
  391. that.title = "修改菜单";
  392. //修改
  393. that.updateMenuSubmit();
  394. } else {
  395. that.title = "添加菜单";
  396. //新增
  397. that.addMenuSubmit();
  398. }
  399. } else {
  400. return false;
  401. }
  402. });
  403. },
  404. //显示添加菜单
  405. addOrEditMenuDialog(val, flag) {
  406. if (val.level === 1) {
  407. this.showFlag = false;
  408. } else {
  409. this.showFlag = true;
  410. }
  411. if ("add" === flag) {
  412. //新增的话,页面的值初始化为定义好的常量
  413. this.menuForm = { ...MENU_FORM };
  414. //新增的话,新增的菜单的pid为当前选中的行的id
  415. this.menuForm.pid = val.id;
  416. this.title = "添加菜单";
  417. } else {
  418. this.title = "修改菜单";
  419. //修改的话,页面的值初始化为列表的具体的内容
  420. Object.assign(this.menuForm, val);
  421. //修改
  422. if (val.level === 2) {
  423. this.showFlag = false;
  424. }
  425. }
  426. this.dialogFormVisible = true;
  427. },
  428. //获取递归取得的全部菜单
  429. getAllMenuList() {
  430. getData().then((res) => {
  431. if (res.code === 20000 && res.data) {
  432. this.tableData = res.data.data;
  433. //console.log('JSON.stringify(this.tableData) ==='+JSON.stringify(this.tableData))
  434. }
  435. });
  436. },
  437. },
  438. };
  439. </script>

分配权限

  1. <template>
  2. <div style="margin: 29px">
  3. <el-tree
  4. ref="tree"
  5. :data="data"
  6. show-checkbox
  7. default-expand-all
  8. node-key="id"
  9. highlight-current
  10. :props="defaultProps"
  11. />
  12. <el-button :disabled="saveBtnDisabled" type="primary" @click="save"
  13. >保存</el-button
  14. >
  15. </div>
  16. </template>
  17. <script>
  18. import {
  19. toAssign,
  20. doAssign,
  21. } from "@/api/permission";
  22. export default {
  23. data() {
  24. return {
  25. saveBtnDisabled: false,
  26. data: [],
  27. roleId: "",
  28. defaultProps: {
  29. children: "children",
  30. label: "name",
  31. },
  32. };
  33. },
  34. watch: {
  35. $route(to, from) {
  36. this.init();
  37. },
  38. },
  39. created() {
  40. this.init();
  41. },
  42. methods: {
  43. init() {
  44. if (this.$route.params && this.$route.params.id) {
  45. this.roleId = this.$route.params.id;
  46. this.getDataList(this.roleId);
  47. }
  48. },
  49. getDataList(roleId) {
  50. toAssign(roleId).then((res) => {
  51. if (res.code === 20000 && res.data.data) {
  52. this.data = res.data.data;
  53. var list = [];
  54. var jsonList = JSON.parse(JSON.stringify(this.data));
  55. var llll = JSON.stringify(this.data);
  56. console.log("this.data========================= " + this.data);
  57. console.log("jsonList========================= " + jsonList);
  58. console.log(
  59. "JSON.stringify(this.data)========================= " +
  60. JSON.stringify(this.data)
  61. );
  62. this.getJsonList(list, jsonList[0]["children"]);
  63. this.$refs.tree.setCheckedKeys(list);
  64. }
  65. });
  66. },
  67. //获取所有的角色的权限
  68. getJsonList(list, jsonList) {
  69. for (var i = 0; i < jsonList.length; i++) {
  70. if (
  71. jsonList[i]["hasSelect"] == true &&
  72. jsonList[i]["children"].length === 0
  73. ) {
  74. list.push(jsonList[i]["id"]);
  75. }
  76. if (jsonList[i]["children"].length > 0) {
  77. this.getJsonList(list, jsonList[i]["children"]);
  78. }
  79. }
  80. },
  81. save() {
  82. this.saveBtnDisabled = true;
  83. var beforeIds = this.$refs.tree.getHalfCheckedKeys().join(",");
  84. var afterIds = this.$refs.tree.getCheckedKeys().join(",");
  85. var ids = beforeIds + "," + afterIds;
  86. if (ids === ",") {
  87. ids = [];
  88. }
  89. console.log(ids);
  90. doAssign(this.roleId, ids).then((res) => {
  91. if (res.code === 20000 && res.success) {
  92. this.$message({
  93. type: "info",
  94. message: "保存成功!",
  95. });
  96. this.$router.push({ path: "/role" });
  97. } else {
  98. this.$message({
  99. type: "info",
  100. message: "保存失败!",
  101. });
  102. }
  103. });
  104. },
  105. },
  106. };
  107. </script>
  108. <style>
  109. </style>

路由

  1. import Vue from 'vue'
  2. import VueRouter from 'vue-router'
  3. import Home from '@/views/Home.vue'
  4. import User from '@/views/sys/user/User.vue'
  5. import Main from '@/views/Main.vue'
  6. import store from '@/store'
  7. import { getToken } from '@/utils/auth'
  8. import { login, logout, getInfo } from '@/api/login'
  9. Vue.use(VueRouter)
  10. // 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
  11. // 1. 定义 (路由) 组件。
  12. // 可以从其他文件 import 进来
  13. // 2. 定义路由
  14. // 每个路由应该映射一个组件。 其中"component" 可以是
  15. // 通过 Vue.extend() 创建的组件构造器,
  16. // 或者,只是一个组件配置对象。
  17. // 我们晚点再讨论嵌套路由。
  18. const routes = [
  19. {
  20. path: '/login',
  21. name: 'Login',
  22. component: () => import('@/views/Login.vue')
  23. },
  24. //主路由
  25. // {
  26. // path: '/',
  27. // component: Main,
  28. // redirect: '/home',
  29. // children: [
  30. // //子路由
  31. // { path: 'home', name: "home", component: Home },//首页
  32. // // { path: 'user', name: "user", component: User },//用户管理
  33. // // { path: 'role', name: "role", component: () => import("@/views/sys/Role.vue") },//角色管理
  34. // // { path: 'menu', name: "menu", component: () => import("@/views/sys/Menu.vue") },//菜单管理管理
  35. // ]
  36. // },
  37. // {
  38. // path: '/user',
  39. // name: 'User',
  40. // component: User
  41. // },
  42. ]
  43. // 3. 创建 router 实例,然后传 `routes` 配置
  44. // 你还可以传别的配置参数, 不过先这么简单着吧。
  45. const router = new VueRouter({
  46. mode: 'history', // 去掉url中的#
  47. routes // (缩写) 相当于 routes: routes
  48. })
  49. // 4. 创建和挂载根实例。挂载到main.js的根节点
  50. // 记得要通过 router 配置参数注入路由,
  51. // 从而让整个应用都有路由功能
  52. // const app = new Vue({
  53. // router
  54. // }).$mount('#app')
  55. // 防止连续点击多次路由报错
  56. // 获取原型对象push函数
  57. const originalPush = VueRouter.prototype.push
  58. // 获取原型对象replace函数
  59. const originalReplace = VueRouter.prototype.replace
  60. // 修改原型对象中的push函数
  61. VueRouter.prototype.push = function push(location) {
  62. return originalPush.call(this, location).catch(err => err)
  63. }
  64. // 修改原型对象中的replace函数
  65. VueRouter.prototype.replace = function replace(location) {
  66. return originalReplace.call(this, location).catch(err => err)
  67. }
  68. //模拟菜单数据
  69. //const authoritys = ['sys:user:list', "sys:user:save", "sys:user:delete"]
  70. const menuData1 = [
  71. // {
  72. // path: "/",
  73. // name: "home",
  74. // label: "首页",
  75. // icon: "s-home",
  76. // url: "Home/Home",
  77. // },
  78. {
  79. label: "权限管理",
  80. name: "system",
  81. icon: "location",
  82. children: [
  83. {
  84. path: "/user",
  85. name: "user",
  86. label: "用户管理",
  87. icon: "setting",
  88. component: "sys/user/User",
  89. },
  90. {
  91. path: '/sys/role/distribution/:id',
  92. name: '角色权限',
  93. component: 'sys/role/roleForm',
  94. meta: { title: '角色权限', icon: 'table' },
  95. hidden: true
  96. },
  97. {
  98. path: '/userForm/:id',
  99. name: '角色权限',
  100. component: 'sys/user/userForm',
  101. meta: { title: '角色权限', icon: 'table' },
  102. hidden: true
  103. },
  104. {
  105. path: "/role",
  106. name: "role",
  107. label: "角色管理",
  108. icon: "setting",
  109. component: "sys/role/Role",
  110. },
  111. {
  112. path: "/menu",
  113. name: "menu",
  114. label: "菜单管理",
  115. icon: "setting",
  116. component: "sys/menu/Menu",
  117. },
  118. ],
  119. },
  120. ]
  121. // 拼装动态路由
  122. const manageRoute = {
  123. path: '/',
  124. component: Main,
  125. redirect: '/login',
  126. children: [
  127. //子路由
  128. { path: 'home', name: "home", component: Home },//首页
  129. ]
  130. }
  131. //获取数据
  132. //菜单
  133. // store.commit('setMenuList', menuData1)
  134. //权限用户
  135. //localStorage.setItem("menus1", JSON.stringify(menuData1))
  136. // 注意:刷新页面会导致页面路由重置
  137. const setRoutes = () => {
  138. //const storeMenus = localStorage.getItem("menus");
  139. const storeMenus = localStorage.getItem("menus");
  140. if (storeMenus) {
  141. // 获取当前的路由对象名称数组
  142. const currentRouteNames = router.getRoutes().map(v => v.name)
  143. if (!currentRouteNames.includes('home')) {
  144. const menus = JSON.parse(storeMenus)
  145. menus.forEach(item => {
  146. if (item.path) { // 当且仅当path不为空的时候才去设置路由
  147. let flag = false;
  148. if (item.hidden) {
  149. flag = true;
  150. }
  151. let itemMenu = {
  152. path: item.path,
  153. name: item.name,
  154. hidden: flag,
  155. component: () => import('../views/' + item.component + '.vue')
  156. }
  157. manageRoute.children.push(itemMenu)
  158. } else if (item.children.length) {
  159. item.children.forEach(item => {
  160. let flag = false;
  161. if (item.hidden) {
  162. flag = true;
  163. }
  164. if (item.path) {
  165. let itemMenu = {
  166. path: item.path,
  167. name: item.name,
  168. hidden: flag,
  169. component: () => import('../views/' + item.component + '.vue')
  170. }
  171. manageRoute.children.push(itemMenu)
  172. }
  173. })
  174. }
  175. })
  176. // 动态添加到现在的路由对象中去
  177. router.addRoute(manageRoute)
  178. }
  179. }
  180. }
  181. // 重置我就再set一次路由
  182. setRoutes()
  183. //转成路由
  184. // const menuToRoute = (item) => {
  185. // if (!item.component) {
  186. // return null
  187. // }
  188. // // let route = {
  189. // // name: item.name,
  190. // // path: item.path.replace("/", ""),
  191. // // meta: {
  192. // // icon: item.icon,
  193. // // title: item.title,
  194. // // }
  195. // // }
  196. // // route.component= () => import('../views/' + item.component + '.vue')
  197. // // route.component=()=>import('@/views/'+item.component+'.vue');
  198. // // route.component = () => import('@/views/' + item.component + '.vue')
  199. // let route = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.component + '.vue') }
  200. // return route
  201. // }
  202. // router.beforeEach((to, from, next) => {
  203. // let that = this
  204. // getInfo(store.state.token).then(response => {
  205. // const data = response.data
  206. // if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
  207. // store.commit('SET_ROLES', data.roles)
  208. // }
  209. // const buttonAuthList = []
  210. // menuData = data.permissionList
  211. //
  212. // data.permissionValueList.forEach(button => {
  213. // if (button) {
  214. // buttonAuthList.push(button)
  215. // }
  216. // })
  217. // store.commit('SET_NAME', data.name)
  218. // //commit('SET_AVATAR', data.avatar)
  219. // store.commit('SET_BUTTONS', buttonAuthList)
  220. // }).catch(error => {
  221. // })
  222. // next()
  223. // })
  224. export default router

权限

  1. import router from './router'
  2. import { login, logout, getInfo } from '@/api/login'
  3. import { getToken, setToken, removeToken } from '@/utils/auth'
  4. import http from "@/utils/request";
  5. import qs from "qs";
  6. import store from './store'
  7. router.beforeEach(async (to, from, next) => {
  8. const hasToken = getToken()
  9. if (hasToken) {
  10. if (to.path === '/login') {
  11. // if is logged in, redirect to the home page
  12. next()
  13. } else {
  14. // determine whether the user has obtained his permission roles through getInfo
  15. const hasRoles = store.getters.roles && store.getters.roles.length > 0
  16. if (hasRoles) {
  17. next()
  18. } else {
  19. // get user info
  20. // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
  21. const response = await store.dispatch('GetInfo')
  22. if (response.code === 20000) {
  23. const data = response.data
  24. if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
  25. store.commit('SET_ROLES', data.roles)
  26. }
  27. const buttonAuthList = []
  28. const menuData = data.permissionList
  29. store.commit('setMenuList', menuData)
  30. //权限用户
  31. localStorage.setItem("menus", JSON.stringify(menuData))
  32. data.permissionValueList.forEach(button => {
  33. if (button) {
  34. buttonAuthList.push(button)
  35. }
  36. })
  37. store.commit('SET_NAME', data.name)
  38. //commit('SET_AVATAR', data.avatar)
  39. store.commit('SET_BUTTONS', buttonAuthList)
  40. }
  41. }
  42. }
  43. }
  44. next()
  45. })

mixin

  1. import Vue from "vue"
  2. Vue.mixin({
  3. methods: {
  4. hasAuth(perm) {
  5. var authority = this.$store.state.user.buttons
  6. return authority.indexOf(perm) > -1
  7. }
  8. }
  9. })

security配置

  1. package com.stu.myserver.config;
  2. import com.stu.myserver.security.*;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  7. import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  8. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  9. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  10. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  11. import org.springframework.security.config.http.SessionCreationPolicy;
  12. import org.springframework.security.core.userdetails.UserDetailsService;
  13. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  14. /******************************
  15. * 用途说明: Security配置
  16. * 作者姓名: 公众号:小明的学习圈子 https://www.stucoding.com/
  17. * 创建时间: 2022-07-27 23:16
  18. ******************************/
  19. @Configuration
  20. @EnableWebSecurity
  21. @EnableGlobalMethodSecurity(prePostEnabled = true)
  22. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  23. @Autowired
  24. LoginFailureHandler loginFailureHandler;
  25. @Autowired
  26. LoginSuccessHandler loginSuccessHandler;
  27. @Autowired
  28. CaptchaFilter captchaFilter;
  29. @Autowired
  30. JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
  31. @Autowired
  32. JwtAccessDeniedHandler jwtAccessDeniedHandler;
  33. @Autowired
  34. private UserDetailsService userDetailsService;
  35. @Autowired
  36. JwtLogoutSuccessHandler jwtLogoutSuccessHandler;
  37. @Bean
  38. JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
  39. JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
  40. return jwtAuthenticationFilter;
  41. }
  42. // @Bean
  43. // BCryptPasswordEncoder bCryptPasswordEncoder() {
  44. // return new BCryptPasswordEncoder();
  45. // }
  46. private static final String[] URL_WHITELIST = {
  47. "/user/register",
  48. "/js/**",
  49. "/login",
  50. "/logout",
  51. "/captcha",
  52. "/favicon.ico",
  53. "/login**",
  54. "/login#/login",
  55. "/home/getData",
  56. "captcha/getUserInfo"
  57. };
  58. protected void configure(HttpSecurity http) throws Exception {
  59. http.cors().and().csrf().disable() // 登录配置
  60. .formLogin()
  61. .successHandler(loginSuccessHandler)
  62. .failureHandler(loginFailureHandler)
  63. .and()
  64. .logout()
  65. .logoutSuccessHandler(jwtLogoutSuccessHandler)
  66. // 禁用session
  67. .and()
  68. .sessionManagement()
  69. .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  70. // 配置拦截规则
  71. .and()
  72. .authorizeRequests()
  73. .antMatchers(URL_WHITELIST).permitAll()
  74. .anyRequest().authenticated()
  75. // 异常处理器
  76. .and()
  77. .exceptionHandling()
  78. .authenticationEntryPoint(jwtAuthenticationEntryPoint)
  79. .accessDeniedHandler(jwtAccessDeniedHandler)
  80. // 配置自定义的过滤器
  81. .and()
  82. .addFilter(jwtAuthenticationFilter())
  83. .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class);
  84. }
  85. @Override
  86. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  87. auth.userDetailsService(userDetailsService);
  88. }
  89. }

Redis配置

  1. package com.stu.myserver.config;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.data.redis.connection.RedisConnectionFactory;
  6. import org.springframework.data.redis.core.RedisTemplate;
  7. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  8. import org.springframework.data.redis.serializer.StringRedisSerializer;
  9. /******************************
  10. * 用途说明: redis配置
  11. * 作者姓名: 公众号:小明的学习圈子 https://www.stucoding.com/
  12. * 创建时间: 2022-07-27 23:16
  13. ******************************/
  14. @Configuration
  15. public class RedisConfig {
  16. @Bean
  17. RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  18. RedisTemplate redisTemplate = new RedisTemplate();
  19. redisTemplate.setConnectionFactory(redisConnectionFactory);
  20. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  21. jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper());
  22. redisTemplate.setKeySerializer(new StringRedisSerializer());
  23. redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
  24. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
  25. redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
  26. return redisTemplate;
  27. }
  28. }

跨域配置

  1. package com.stu.myserver.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.cors.CorsConfiguration;
  5. import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
  6. import org.springframework.web.filter.CorsFilter;
  7. import org.springframework.web.servlet.config.annotation.CorsRegistry;
  8. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  9. /******************************
  10. * 用途说明: 跨域
  11. * 作者姓名: 公众号:小明的学习圈子 https://www.stucoding.com/
  12. * 创建时间: 2022-07-27 23:16
  13. ******************************/
  14. @Configuration
  15. public class CorsConfig implements WebMvcConfigurer {
  16. private CorsConfiguration buildConfig() {
  17. CorsConfiguration corsConfiguration = new CorsConfiguration();
  18. corsConfiguration.addAllowedOrigin("*");
  19. corsConfiguration.addAllowedHeader("*");
  20. corsConfiguration.addAllowedMethod("*");
  21. corsConfiguration.addExposedHeader("Authorization");
  22. return corsConfiguration;
  23. }
  24. @Bean
  25. public CorsFilter corsFilter() {
  26. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  27. source.registerCorsConfiguration("/**", buildConfig());
  28. return new CorsFilter(source);
  29. }
  30. @Override
  31. public void addCorsMappings(CorsRegistry registry) {
  32. registry.addMapping("/**")
  33. .allowedOrigins("*")
  34. // .allowCredentials(true)
  35. .allowedMethods("GET", "POST", "DELETE", "PUT")
  36. .maxAge(3600);
  37. }
  38. }
PermissionServiceImpl
  1. package com.stu.myserver.service.impl;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  5. import com.stu.myserver.entity.Permission;
  6. import com.stu.myserver.entity.RolePermission;
  7. import com.stu.myserver.mapper.PermissionMapper;
  8. import com.stu.myserver.service.IPermissionService;
  9. import com.stu.myserver.service.IRolePermissionService;
  10. import com.stu.myserver.service.IUserService;
  11. import org.apache.commons.lang.StringUtils;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.stereotype.Service;
  14. import com.stu.myserver.entity.User;
  15. import org.springframework.util.CollectionUtils;
  16. import java.util.ArrayList;
  17. import java.util.List;
  18. import java.util.stream.Collectors;
  19. /**
  20. * <p>
  21. * 权限 服务实现类
  22. * </p>
  23. *
  24. * @author 程序员小明1024
  25. * @since 2023-08-07
  26. */
  27. @Service
  28. public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {
  29. @Autowired
  30. private IRolePermissionService rolePermissionService;
  31. @Autowired
  32. private IUserService userService;
  33. /***********************************
  34. * 用途说明:获取全部菜单
  35. * 返回值说明:
  36. * @return List<Permission>
  37. ***********************************/
  38. @Override
  39. public List<Permission> listPermissions() {
  40. QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
  41. queryWrapper.orderByDesc("id");
  42. //把查询的所有菜单用递归的方式生成结构化菜单
  43. return buildPermissions(baseMapper.selectList(queryWrapper));
  44. }
  45. /***********************************
  46. * 用途说明:获取全部菜单
  47. * 返回值说明:
  48. * @return List<Permission>
  49. ***********************************/
  50. private List<Permission> buildPermissions(List<Permission> list) {
  51. //创建rootList集合,最终数据封装
  52. List<Permission> rootList = new ArrayList<>();
  53. //遍历所有菜单,得到顶层菜单 pid==0,设置leve =1
  54. for (Permission permission : list) {
  55. //获取顶层菜单,pid=0
  56. if ("0".equals(permission.getPid())) {
  57. //设置level = 1
  58. permission.setLevel(1);
  59. //根据顶层菜单,添加子菜单,封装到rootList
  60. rootList.add(selectChildrenMenu(permission, list));
  61. }
  62. }
  63. return rootList;
  64. }
  65. /***********************************
  66. * 用途说明:递归查询下级菜单
  67. * @param root
  68. * @param list
  69. * 返回值说明:
  70. * @return com.stu.myserver.entity.Permission
  71. ***********************************/
  72. private Permission selectChildrenMenu(Permission root, List<Permission> list) {
  73. //因为要往下级菜单房新的菜单,需要初始化
  74. root.setChildren(new ArrayList<Permission>());
  75. //遍历所有菜单,比较当前对象的id和遍历的子菜单的pid是否相同
  76. for (Permission permission : list) {
  77. if (root.getId().equals(permission.getPid())) {
  78. permission.setLevel(root.getLevel() + 1);
  79. //递归,查询出来的子菜单放到父菜单里
  80. root.getChildren().add(selectChildrenMenu(permission, list));
  81. }
  82. }
  83. return root;
  84. }
  85. /***********************************
  86. * 用途说明:查询所有权限菜单
  87. * 返回值说明:
  88. * @return java.util.List<com.stu.service.acl.entity.Permission>
  89. ***********************************/
  90. @Override
  91. public List<Permission> ListAllPermissions() {
  92. QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
  93. queryWrapper.orderByDesc("id");
  94. return bulidPermission(baseMapper.selectList(queryWrapper));
  95. }
  96. /***********************************
  97. * 用途说明:把返回所有菜单list集合进行封装的方法
  98. * @param list
  99. * 返回值说明:
  100. * @return java.util.List<com.stu.service.acl.entity.Permission>
  101. ***********************************/
  102. private List<Permission> bulidPermission(List<Permission> list) {
  103. //创建list集合,用于数据最终封装
  104. List<Permission> finalNode = new ArrayList<>();
  105. //把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1
  106. for (Permission permission : list) {
  107. //得到顶层菜单 pid=0菜单
  108. if ("0".equals(permission.getPid())) {
  109. permission.setLevel(1);
  110. //根据顶层菜单,向里面进行查询子菜单,封装到finalNode里面
  111. finalNode.add(selectChildren(permission, list));
  112. }
  113. }
  114. return finalNode;
  115. }
  116. /***********************************
  117. * 用途说明:递归查询下级菜单
  118. * @param permission
  119. * @param list
  120. * 返回值说明:
  121. * @return com.stu.service.acl.entity.Permission
  122. ***********************************/
  123. private Permission selectChildren(Permission permission, List<Permission> list) {
  124. //1 因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
  125. permission.setChildren(new ArrayList<Permission>());
  126. //2 遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同
  127. for (Permission child : list) {
  128. if (permission.getId().equals(child.getPid())) {
  129. child.setLevel(permission.getLevel() + 1);
  130. if (child.getChildren() == null) {
  131. child.setChildren(new ArrayList<>());
  132. }
  133. // permission.getChildren().add(child);
  134. // selectChildren(child,list);
  135. permission.getChildren().add(selectChildren(child, list));
  136. }
  137. }
  138. return permission;
  139. }
  140. /***********************************
  141. * 用途说明:递归删除菜单
  142. * @param id
  143. * 返回值说明:
  144. * @return boolean
  145. ***********************************/
  146. @Override
  147. public boolean removeChildById(String id) {
  148. List<String> idList = new ArrayList<>();
  149. selectChildListById(id, idList);
  150. idList.add(id);
  151. return baseMapper.deleteBatchIds(idList) > 0;
  152. }
  153. /***********************************
  154. * 用途说明:根據角色獲取菜單
  155. * @param id
  156. * 返回值说明:
  157. * @return java.util.List<com.stu.service.acl.entity.Permission>
  158. ***********************************/
  159. @Override
  160. public List<Permission> listAllMenu(String id) {
  161. //获取所有菜单
  162. List<Permission> allPermissionList = baseMapper.selectList(new QueryWrapper<>());
  163. //根据角色id呼气角色权限列表
  164. List<RolePermission> rolePermissionsList = rolePermissionService
  165. .list(new QueryWrapper<RolePermission>().eq("role_id", id));
  166. //遍历所有菜单,获取每一项,看是否在权限列表,如果在,就标记
  167. List<String> permissionIdList = rolePermissionsList.stream().map(e -> e.getPermissionId()).collect(Collectors.toList());
  168. allPermissionList.forEach(permission -> {
  169. if (permissionIdList.contains(permission.getId())) {
  170. permission.setHasSelect(true);
  171. } else {
  172. permission.setHasSelect(false);
  173. }
  174. });
  175. /*for (int i = 0; i < allPermissionList.size(); i++) {
  176. Permission permission = allPermissionList.get(i);
  177. for (int m = 0; m < rolePermissionList.size(); m++) {
  178. RolePermission rolePermission = rolePermissionList.get(m);
  179. if(rolePermission.getPermissionId().equals(permission.getId())) {
  180. permission.setSelect(true);
  181. }
  182. }
  183. }*/
  184. return bulidPermission(allPermissionList);
  185. }
  186. /***********************************
  187. * 用途说明:给角色分配菜单权限
  188. * @param roleId
  189. * @param permissionId
  190. * 返回值说明:
  191. * @return boolean
  192. ***********************************/
  193. @Override
  194. public boolean saveRolePermissionrelationShip(String roleId, String[] permissionId) {
  195. //删除旧的权限
  196. boolean ttt = rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", roleId));
  197. if (null != permissionId && permissionId.length > 0) {
  198. List<RolePermission> list = new ArrayList<>();
  199. for (String id : permissionId) {
  200. RolePermission rolePermission = new RolePermission();
  201. rolePermission.setRoleId(roleId);
  202. rolePermission.setPermissionId(id);
  203. list.add(rolePermission);
  204. }
  205. return rolePermissionService.saveBatch(list);
  206. }
  207. return true;
  208. }
  209. /***********************************
  210. * 用途说明:根据用户id查询有权限的菜单
  211. * @param id
  212. * 返回值说明:
  213. * @return java.util.List<java.lang.String>
  214. ***********************************/
  215. @Override
  216. public List<String> selectPermissionValueListByUserId(String id) {
  217. List<String> list;
  218. if (checkAdmin(id)) {
  219. //如果是超级管理员获取所有权限
  220. list = baseMapper.selectAllPermissionValue();
  221. } else {
  222. //根据用户id查询所有权限
  223. list = baseMapper.selectPermissionValueByUserId(id);
  224. }
  225. return list;
  226. }
  227. /***********************************
  228. * 用途说明:根据用户id查询所有权限的菜单详细列表
  229. * @param userId
  230. * 返回值说明:
  231. * @return java.util.List<org.json.JSONObject>
  232. ***********************************/
  233. @Override
  234. public List<JSONObject> selectPermissionByUserId(String userId) {
  235. List<Permission> selectPermissionList = null;
  236. if (checkAdmin(userId)) {
  237. //如果是超级管理员获取所有权限
  238. selectPermissionList = baseMapper.selectList(null);
  239. } else {
  240. //根据用户id查询所有权限
  241. selectPermissionList = baseMapper.selectPermissionByUserId(userId);
  242. }
  243. //先转换成树状
  244. List<Permission> permissionList = bulidPermission(selectPermissionList);
  245. //然后转化成前端需要的格式
  246. List<JSONObject> result = bulidJson(permissionList);
  247. return result;
  248. }
  249. /***********************************
  250. * 用途说明:转化成前端需要的格式
  251. * @param permissionList
  252. * 返回值说明:
  253. * @return java.util.List<org.json.JSONObject>
  254. ***********************************/
  255. private List<JSONObject> bulidJson(List<Permission> permissionList) {
  256. List<JSONObject> menus = new ArrayList<>();
  257. if (permissionList.size() == 1) {
  258. Permission topNode = permissionList.get(0);
  259. //组建左侧一级菜单
  260. List<Permission> oneMenuList = topNode.getChildren();
  261. for (Permission one : oneMenuList) {
  262. JSONObject oneMenu = new JSONObject();
  263. oneMenu.put("path", one.getPath());
  264. oneMenu.put("component", one.getComponent());
  265. oneMenu.put("redirect", "noredirect");//第一级不需要重定向
  266. oneMenu.put("name", "name_" + one.getId());
  267. oneMenu.put("title", one.getName());
  268. oneMenu.put("label", one.getName());
  269. oneMenu.put("icon", one.getIcon());
  270. oneMenu.put("hidden", false);//一级不需要因此,3级需要
  271. JSONObject oneMeta = new JSONObject();
  272. oneMeta.put("title", one.getName());
  273. oneMeta.put("icon", one.getIcon());
  274. oneMenu.put("meta", oneMeta);
  275. List<JSONObject> children = new ArrayList<>();
  276. List<Permission> twoMenuList = one.getChildren();//二级菜单
  277. for (Permission two : twoMenuList) {
  278. JSONObject twoMenu = new JSONObject();
  279. twoMenu.put("path", two.getPath());
  280. twoMenu.put("component", two.getComponent());
  281. twoMenu.put("title", two.getName());
  282. twoMenu.put("label", two.getName());
  283. twoMenu.put("icon", two.getIcon());
  284. // twoMenu.put("redirect", "noredirect");//第一级不需要重定向
  285. twoMenu.put("name", "name_" + two.getId());
  286. twoMenu.put("hidden", false);//一级不需要因此,3级需要
  287. JSONObject twoMeta = new JSONObject();
  288. twoMeta.put("title", two.getName());
  289. twoMeta.put("icon", two.getIcon());
  290. twoMenu.put("meta", twoMeta);
  291. children.add(twoMenu);
  292. //功能按钮
  293. List<Permission> threeMenuList = two.getChildren();
  294. for (Permission three : threeMenuList) {
  295. if (StringUtils.isEmpty(three.getPath())) {
  296. continue;
  297. }
  298. JSONObject threeMenu = new JSONObject();
  299. threeMenu.put("path", three.getPath());
  300. threeMenu.put("component", three.getComponent());
  301. // threeMenu.put("redirect", "noredirect");//第一级不需要重定向
  302. threeMenu.put("name", "name_" + three.getId());
  303. threeMenu.put("title", three.getName());
  304. threeMenu.put("label", three.getName());
  305. threeMenu.put("icon", three.getIcon());
  306. threeMenu.put("hidden", true);//一级不需要因此,3级需要
  307. JSONObject threeMeta = new JSONObject();
  308. threeMeta.put("title", three.getName());
  309. threeMeta.put("icon", three.getIcon());
  310. threeMenu.put("meta", threeMeta);
  311. children.add(threeMenu);
  312. }
  313. }
  314. oneMenu.put("children", children);
  315. menus.add(oneMenu);
  316. }
  317. }
  318. return menus;
  319. }
  320. /***********************************
  321. * 用途说明:判断是否管理员
  322. * @param id
  323. * 返回值说明:
  324. * @return boolean
  325. ***********************************/
  326. private boolean checkAdmin(String id) {
  327. User user = userService.getById(id);
  328. if (user != null && "admin".equals(user.getUsername())) {
  329. return true;
  330. }
  331. return false;
  332. }
  333. /***********************************
  334. * 用途说明:根据当前菜单id查询他的子子孙孙id,封装到list集合
  335. * @param id
  336. * @param idList
  337. * 返回值说明:
  338. ***********************************/
  339. private void selectChildListById(String id, List<String> idList) {
  340. //查询当前菜单的下级
  341. QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
  342. queryWrapper.eq("pid", id);
  343. queryWrapper.select("id");
  344. List<Permission> childList = baseMapper.selectList(queryWrapper);
  345. //把childIdList里面菜单id值获取出来,封装idList里面,做递归查询
  346. childList.forEach(item -> {
  347. idList.add(item.getId());
  348. selectChildListById(item.getId(), idList);
  349. });
  350. }
  351. }

IndexServiceImpl

  1. package com.stu.myserver.service.impl;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.stu.myserver.entity.Role;
  4. import com.stu.myserver.entity.User;
  5. import com.stu.myserver.exception.CustomException;
  6. import com.stu.myserver.service.IPermissionService;
  7. import com.stu.myserver.service.IRoleService;
  8. import com.stu.myserver.service.IUserService;
  9. import com.stu.myserver.service.IndexService;
  10. import com.stu.myserver.utils.ResultCodeEnum;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.data.redis.core.RedisTemplate;
  13. import org.springframework.stereotype.Service;
  14. import java.util.HashMap;
  15. import java.util.List;
  16. import java.util.Map;
  17. import java.util.stream.Collectors;
  18. /******************************
  19. * 用途说明:
  20. * 作者姓名: Administrator
  21. * 创建时间: 2022-09-01 22:34
  22. ******************************/
  23. @Service
  24. public class IndexServiceImpl implements IndexService {
  25. @Autowired
  26. private IUserService userService;
  27. @Autowired
  28. private IRoleService roleService;
  29. @Autowired
  30. private IPermissionService permissionService;
  31. @Autowired
  32. private RedisTemplate redisTemplate;
  33. /***********************************
  34. * 用途说明:根据用户明获取用户登录信息
  35. * @param userName
  36. * 返回值说明:
  37. * @return java.util.Map<java.lang.String, java.lang.Object>
  38. ***********************************/
  39. @Override
  40. public Map<String, Object> getUserInfo(String userName) {
  41. Map<String, Object> result = new HashMap<>();
  42. User user = userService.selectByUserName(userName);
  43. if (user == null) {
  44. throw new CustomException(ResultCodeEnum.FETCH_USERINFO_ERROR);
  45. }
  46. //根据用户id获取角色
  47. List<Role> roleList = roleService.selectRoleByUserId(user.getId());
  48. //转换成角色名称列表
  49. List<String> roleNameList = roleList.stream()
  50. .map(item -> item.getRoleName()).collect(Collectors.toList());
  51. //前端框架必须返回一个角色,否则报错,如果没有角色,返回一个空角色
  52. if (roleNameList.size() == 0) {
  53. roleNameList.add("");
  54. }
  55. List<String> permissionValueList = permissionService.selectPermissionValueListByUserId(user.getId());
  56. redisTemplate.opsForValue().set(userName, permissionValueList);
  57. List<String> permissionValueLisst = (List<String>) redisTemplate.opsForValue().get(userName);
  58. result.put("name", user.getUsername());
  59. result.put("roles", roleNameList);
  60. result.put("permissionValueList", permissionValueList);
  61. return result;
  62. }
  63. /***********************************
  64. * 用途说明:根据用户动态获取菜单
  65. * @param userName
  66. * 返回值说明:
  67. * @return java.util.List<org.json.JSONObject>
  68. ***********************************/
  69. @Override
  70. public List<JSONObject> getMenu(String userName) {
  71. User user = userService.selectByUserName(userName);
  72. if (user == null) {
  73. throw new CustomException(ResultCodeEnum.FETCH_USERINFO_ERROR);
  74. }
  75. //根据用户动态获取菜单
  76. return permissionService.selectPermissionByUserId(user.getId());
  77. }
  78. }

RoleServiceImpl

  1. package com.stu.myserver.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  3. import com.stu.myserver.entity.Role;
  4. import com.stu.myserver.entity.UserRole;
  5. import com.stu.myserver.mapper.RoleMapper;
  6. import com.stu.myserver.service.IRoleService;
  7. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  8. import com.stu.myserver.service.IUserRoleService;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Service;
  11. import java.util.ArrayList;
  12. import java.util.HashMap;
  13. import java.util.List;
  14. import java.util.Map;
  15. import java.util.stream.Collectors;
  16. /**
  17. * <p>
  18. * 服务实现类
  19. * </p>
  20. *
  21. * @author 程序员小明1024
  22. * @since 2023-06-28
  23. */
  24. @Service
  25. public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
  26. @Autowired
  27. private IUserRoleService userRoleService;
  28. /***********************************
  29. * 用途说明:根据用户获取角色
  30. * @param userId
  31. * 返回值说明:
  32. * @return java.util.List<com.stu.service.acl.entity.Permission>
  33. ***********************************/
  34. @Override
  35. public Map<String, Object> findRoleByUserId(String userId) {
  36. //获取所有角色
  37. List<Role> allRoleList = baseMapper.selectList(new QueryWrapper<>());
  38. //根据用户id获取角色列表
  39. List<UserRole> existUserRoleList = userRoleService
  40. .list(new QueryWrapper<UserRole>().eq("user_id", userId).select("role_id"));
  41. //遍历所有菜单,获取每一项,看是否在权限列表,如果在,就标记
  42. List<String> existRoleLists = existUserRoleList.stream().map(e -> e.getRoleId()).collect(Collectors.toList());
  43. List<Role> assignRoles = new ArrayList<>();
  44. allRoleList.forEach(role -> {
  45. if (existRoleLists.contains(role.getId())) {
  46. assignRoles.add(role);
  47. }
  48. });
  49. Map<String, Object> roleMap = new HashMap<>();
  50. roleMap.put("assignRoles", assignRoles);
  51. roleMap.put("allRoleList", allRoleList);
  52. return roleMap;
  53. }
  54. /***********************************
  55. * 用途说明:给用户分配角色权限
  56. * @param userId
  57. * @param roleIds
  58. * 返回值说明:
  59. * @return boolean
  60. ***********************************/
  61. @Override
  62. public boolean saveUserRelationShip(String userId, String[] roleIds) {
  63. //删除旧的所有角色权限
  64. userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", userId));
  65. List<UserRole> list = new ArrayList<>();
  66. for (String id : roleIds) {
  67. UserRole rolePermission = new UserRole();
  68. rolePermission.setRoleId(id);
  69. rolePermission.setUserId(userId);
  70. list.add(rolePermission);
  71. }
  72. return userRoleService.saveBatch(list);
  73. }
  74. /***********************************
  75. * 用途说明:根据userid获取用户信息
  76. * @param userId
  77. * 返回值说明:
  78. * @return java.util.List<com.stu.service.acl.entity.Role>
  79. ***********************************/
  80. @Override
  81. public List<Role> selectRoleByUserId(String userId) {
  82. //根据用户id获取角色列表
  83. List<UserRole> userRoleList = userRoleService
  84. .list(new QueryWrapper<UserRole>().eq("user_id", userId).select("role_id"));
  85. //遍历所有菜单,获取每一项,看是否在权限列表,如果在,就标记
  86. List<String> roleIdLists = userRoleList.stream().map(e -> e.getRoleId()).collect(Collectors.toList());
  87. List<Role> roleList = new ArrayList<>();
  88. if (roleIdLists.size() > 0) {
  89. roleList = baseMapper.selectBatchIds(roleIdLists);
  90. }
  91. return roleList;
  92. }
  93. }

CodeGenerator

  1. package com.stu.myserver.utils;
  2. import com.baomidou.mybatisplus.annotation.FieldFill;
  3. import com.baomidou.mybatisplus.generator.FastAutoGenerator;
  4. import com.baomidou.mybatisplus.generator.config.OutputFile;
  5. import com.baomidou.mybatisplus.generator.fill.Column;
  6. import java.util.Collections;
  7. /******************************
  8. * 用途说明:
  9. * 作者姓名:公众号:程序员小明1024
  10. * 创建时间: 2023-06-23 14:52
  11. ******************************/
  12. public class CodeGenerator {
  13. public static void main(String[] args) {
  14. generate();
  15. }
  16. private static void generate() {
  17. String projectPath = System.getProperty("user.dir");
  18. FastAutoGenerator.create("jdbc:mysql://localhost:3306/2023Java?serverTimezone=Asia/Shanghai", "root", "study")
  19. .globalConfig(builder -> {
  20. builder.author("公众号 小明的学习圈子") // 设置作者
  21. .enableSwagger() // 开启 swagger 模式
  22. .fileOverride() // 覆盖已生成文件
  23. .outputDir(projectPath + "/src/main/java"); // 指定输出目录
  24. })
  25. .packageConfig(builder -> {
  26. builder.parent("com.stu.myserver") // 设置父包名
  27. .moduleName(null) // 设置父包模块名
  28. .pathInfo(Collections.singletonMap(OutputFile.mapperXml, projectPath + "/src/main/resources/mapper")); // 设置mapperXml生成路径
  29. })
  30. .strategyConfig(builder -> {
  31. builder.entityBuilder().enableLombok()
  32. .addTableFills(new Column("gmt_create", FieldFill.INSERT))
  33. .addTableFills(new Column("gmt_modified", FieldFill.INSERT_UPDATE));;
  34. // builder.mapperBuilder().enableMapperAnnotation().build();
  35. builder.controllerBuilder().enableHyphenStyle() // 开启驼峰转连字符
  36. .enableRestStyle(); // 开启生成@RestController 控制器
  37. builder.addInclude("acl_user_role") // 设置需要生成的表名
  38. .addTablePrefix("acl_", "sys_"); // 设置过滤表前缀
  39. })
  40. // .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
  41. .execute();
  42. }
  43. }
ResponseUtil
  1. package com.stu.myserver.utils;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import org.springframework.http.HttpStatus;
  4. import org.springframework.http.MediaType;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.IOException;
  7. /******************************
  8. * 用途说明:需要寫入response的數據
  9. * 作者姓名: Administrator
  10. * 创建时间: 2022-09-01 20:44
  11. ******************************/
  12. public class ResponseUtil {
  13. /*这段代码是一个用于在Java Web应用中向客户端发送JSON响应的方法。让我逐行解释其功能:
  14. 1. `public static void out(HttpServletResponse response, R r)`:
  15. 这是一个公共静态方法,它接受两个参数,一个是`HttpServletResponse`对象,
  16. 另一个是泛型`R`的对象`r`。`HttpServletResponse`对象用于设置HTTP响应的状态码、内容类型和写入响应数据。
  17. 2. `ObjectMapper mapper = new ObjectMapper();`:在方法内部创建了一个Jackson库
  18. 的`ObjectMapper`对象。Jackson库是用于在Java对象和JSON之间进行序列化和反序列化的流行库。
  19. 这个`ObjectMapper`对象将用于将`r`对象转换为JSON格式。
  20. 3. `response.setStatus(HttpStatus.OK.value());`:设置HTTP响应的状态码为200 OK。这表示请求已成功处理。
  21. 4. `response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);`:
  22. 设置HTTP响应的内容类型为"application/json;charset=UTF-8",表示响应体将包含JSON数据,并且使用UTF-8字符编码。
  23. 5. `mapper.writeValue(response.getWriter(), r);`:使用`ObjectMapper`
  24. 将`r`对象序列化为JSON格式,并将其写入`HttpServletResponse`的输出流(通过`response.getWriter()`
  25. 获得的输出流)。这样,JSON数据将作为HTTP响应的内容发送给客户端。
  26. 总之,这段代码的目的是将一个Java对象`r`序列化为JSON格式,并将其作为HTTP响应的内容发送给客户端,
  27. 同时设置响应的状态码和内容类型。这通常用于Web应用程序中的API端点,以便向客户端提供结构化的数据响应。
  28. */ public static void out(HttpServletResponse response, R r) {
  29. ObjectMapper mapper = new ObjectMapper();
  30. response.setStatus(HttpStatus.OK.value());
  31. response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
  32. try {
  33. mapper.writeValue(response.getWriter(), r);
  34. } catch (IOException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }

更多内容阅读原文

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/53918
推荐阅读
相关标签
  

闽ICP备14008679号