当前位置: 首页 > news >正文

权限管理---尚硅谷

1.项目基础
2.定义统一返回结果对象
3.Nodejs
4.前端内容编写
5.菜单详情
6.SpringSecurity权限管理
7.添加登录日志
8.操作日志
9.后端打包
10.前端打包
11.动态sql日期的判断

项目基础

在这里插入图片描述

定义统一返回结果对象

  1. 定义全局统一返回结果类
import lombok.Data;

/**
 * 全局统一返回结果类
 *
 */
@Data
public class Result<T> {

    //返回码
    private Integer code;

    //返回消息
    private String message;

    //返回数据
    private T data;

    public Result(){}

    // 返回数据
    protected static <T> Result<T> build(T data) {
        Result<T> result = new Result<T>();
        if (data != null)
            result.setData(data);
        return result;
    }

    public static <T> Result<T> build(T body, Integer code, String message) {
        Result<T> result = build(body);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        Result<T> result = build(body);
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());
        return result;
    }

    public static<T> Result<T> ok(){
        return Result.ok(null);
    }

    /**
     * 操作成功
     * @param data  baseCategory1List
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.SUCCESS);
    }

    public static<T> Result<T> fail(){
        return Result.fail(null);
    }

    /**
     * 操作失败
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> fail(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.FAIL);
    }

    public Result<T> message(String msg){
        this.setMessage(msg);
        return this;
    }

    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }
}
  1. 定义统一返回结果状态信息类
import lombok.Getter;

/**
 * 统一返回结果状态信息类
 *
 */
@Getter
public enum ResultCodeEnum {

    SUCCESS(200,"成功"),
    FAIL(201, "失败"),
    SERVICE_ERROR(2012, "服务异常"),
    DATA_ERROR(204, "数据异常"),
    ILLEGAL_REQUEST(205, "非法请求"),
    REPEAT_SUBMIT(206, "重复提交"),
    ARGUMENT_VALID_ERROR(210, "参数校验异常"),

    LOGIN_AUTH(208, "未登陆"),
    PERMISSION(209, "没有权限"),
    ACCOUNT_ERROR(214, "账号不正确"),
    PASSWORD_ERROR(215, "密码不正确"),
    LOGIN_MOBLE_ERROR( 216, "账号不正确"),
    ACCOUNT_STOP( 217, "账号已停用"),
    NODE_ERROR( 218, "该节点下有子节点,不可以删除")
    ;

    private Integer code;

    private String message;

    private ResultCodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}
  1. 编写controller,返回对象

在这里插入图片描述

Node.js

在这里插入图片描述

NPM 构建前端项目-管理依赖

在这里插入图片描述

模块化开发

  1. 设置方法,设置那些方法可以被其他js调用
    在这里插入图片描述

  2. 引入js文件,调用其方法
    在这里插入图片描述

ES6写法

  1. 定义方法,加上export关键字
    在这里插入图片描述
  2. import 的方式 只取需要的方法即可,多个方法用逗号分隔
    在这里插入图片描述
  3. 需要进行转码 将自己转为es5 babel 文件 -d 转后的文件名称
    在这里插入图片描述

es6 的第二种写法

  1. 定义方法

在这里插入图片描述2. 调用方法
在这里插入图片描述
3. 进行转码操作,运行操作
babel es6-2 -d es5-2
babel-node --presets env 2.js在这里插入图片描述
npm run dev

vue修改访问本地端口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

角色列表的实现

  1. 添加角色管理路由
    在这里插入图片描述

角色开发 创建路由 创建页面

在这里插入图片描述

在这里插入图片描述

2.Api定义接口

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

3.调用api方法,获取响应的数据

在这里插入图片描述
在这里插入图片描述

4.把接口返回的数据进行处理

查询

在这里插入图片描述
列表
在这里插入图片描述

3. 分页

在这里插入图片描述

4. 列表删除

在这里插入图片描述

新增方法

在这里插入图片描述

修改方法

在这里插入图片描述

批量删除

在这里插入图片描述

<template>
  <div class="app-container">
    角色列表
    <!--查询表单-->
    <div class="search-div">
      <el-form label-width="70px" size="small">
        <el-row>
          <el-col :span="24">
            <el-form-item label="角色名称">
              <el-input style="width: 100%" v-model="searchObj.roleName" placeholder="角色名称"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row style="display:flex">
          <el-button type="primary" icon="el-icon-search" size="mini"  @click="fetchData()">搜索</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetData">重置</el-button>
        </el-row>
      </el-form>
    </div>
    <!-- 工具条 -->
  <div class="tools-div">
    <el-button type="success" icon="el-icon-plus" size="mini" @click="add">添 加</el-button>
    <el-button class="btn-add" size="mini" @click="batchRemove()" >批量删除</el-button>
  </div>
    <!-- 表格  listLoading 页面加载转圈效果   :data="list" -- list 每页的列表数据    -->
    <el-table
      v-loading="listLoading"
      :data="list"           
      stripe
      border
      style="width: 100%;margin-top: 10px;"


      @selection-change="handleSelectionChange">// 改变复选框就会触发条件 

      <el-table-column type="selection"/>  // table 组件上添加复选框
      

      <el-table-column
        label="序号"
        width="70"
        align="center">
        <template slot-scope="scope">
          {{ (page - 1) * limit + scope.$index + 1 }}
        </template>
      </el-table-column>

      <el-table-column prop="roleName" label="角色名称" />
      <el-table-column prop="roleCode" label="角色编码" />
      <el-table-column prop="createTime" label="创建时间" width="160"/>
      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <el-button type="primary" icon="el-icon-edit" size="mini" @click="edit(scope.row.id)" title="修改"/>
          <el-button type="danger" icon="el-icon-delete" size="mini" @click="removeDataById(scope.row.id)" title="删除"/>
          <el-button type="warning" icon="el-icon-baseball" size="mini" @click="showAssignAuth(scope.row)" title="分配权限"/>
        </template>
      </el-table-column>
    </el-table>

  <!-- 分页组件 -->
    <el-pagination
      :current-page="page"
      :total="total"
      :page-size="limit"
      style="padding: 30px 0; text-align: center;"
      layout="total, prev, pager, next, jumper"
      @current-change="fetchData"
    />

    <el-dialog title="添加/修改" :visible.sync="dialogVisible" width="40%" >
          <el-form ref="dataForm" :model="sysRole" label-width="150px" size="small" style="padding-right: 40px;">
            <el-form-item label="角色名称">
              <el-input v-model="sysRole.roleName"/>
            </el-form-item>
            <el-form-item label="角色编码">
              <el-input v-model="sysRole.roleCode"/>
            </el-form-item>
          </el-form>
          <span slot="footer" class="dialog-footer">
            <el-button @click="dialogVisible = false" size="small" icon="el-icon-refresh-right">取 消</el-button>
            <el-button type="primary" icon="el-icon-check" @click="saveOrUpdate()" size="small">确 定</el-button>
          </span>
    </el-dialog>
  </div>
</template>
<script>
//引入定义接口的js文件
import api from '@/api/system/role'

export default {
  //定义初始值/初始变量
  data() {
    return {
      listLoading:false,//是否显示加载
      list:[],//角色列表
      total:0,//总记录数
      page:1,//当前页
      limit:3,//每页显示记录数
      
      searchObj:{},//条件查询封装对象

      dialogVisible: false,//弹出框
      sysRole:{}, //封装添加表单数据
      selectValue:[] //复选框选择内容封装数组
    }
  },
  //页面渲染之前执行
  created() {
    //调用列表方法
    this.fetchData()
  },
  methods:{//具体方法
    //跳转分配菜单权限
    showAssignAuth(row) {
      this.$router.push('/system/assignAuth?id='+row.id+'&roleName='+row.roleName);
    },
    //复选框发生变化执行方法
    handleSelectionChange(selection) {
      this.selectValue = selection
      //console.log(this.selectValue)
    },
    //批量删除
    batchRemove() {
      //判断
      if(this.selectValue.length==0) {
        this.$message.warning('请选择要删除的记录!')
        return
      }
      this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          //数组
          var idList = []
          //获取多个复选框对应id,封装到数组里面
          // [1,2,3]
          for(var i=0;i<this.selectValue.length;i++) {
            var obj = this.selectValue[i]
            //id值
            var id = obj.id
            //放到数组里面
            idList.push(id)
          }
          api.batchRemove(idList).then(response => {
              //提示
              this.$message({
                type: 'success',
                message: '删除成功!'
              });
              //刷新
              this.fetchData()
          })
        })
    },
    //修改-数据回显
    edit(id) {
      //弹出框
      this.dialogVisible = true
      api.getRoleId(id).then(response => {
        this.sysRole = response.data
      })
    },
    //点击确定
    saveOrUpdate() {
      //判断添加还是修改
      if(!this.sysRole.id) {
        //添加
        this.saveRole()
      } else {
        this.updateRole()
      }
    },
    //修改的方法
    updateRole() {
      api.update(this.sysRole)
        .then(response => {
          //提示
          this.$message({
            type: 'success',
            message: '修改成功!'
          });
          //关闭弹框
          this.dialogVisible = false
          //刷新页面
          this.fetchData()
        })
    },
    //添加的方法
    saveRole() {
      api.saveRole(this.sysRole)
        .then(response => {
          //提示
          this.$message({
            type: 'success',
            message: '添加成功!'
          });
          //关闭弹框
          this.dialogVisible = false
          //刷新页面
          this.fetchData()
        })
    },
    //点击添加,弹出框
    add() {
      this.dialogVisible = true
      this.sysRole = {}
    },
    //删除
    removeDataById(id) {
       this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          //调用方法删除
          api.removeId(id)
            .then(response => {
              //提示
              this.$message({
                type: 'success',
                message: '删除成功!'
              });
              //刷新
              this.fetchData()
          })
        })
    },
    //重置
    resetData() {
      //清空表单
      this.searchObj = {}
      //查询所有数据
      this.fetchData()
    },
    //条件分页查询列表
    //pageNum 查询页数
    fetchData(pageNum=1) {
      //页数赋值
      this.page = pageNum
      //ajax
      api.getPageList(this.page,this.limit,this.searchObj)
        .then(response => {      // 调用接口成功执行then方法
          //this.listLoading = false
          //console.log(response)
          //每页数据列表
          this.list = response.data.records
          //总记录数
          this.total = response.data.total
        })
    }
  }
}
</script>


api

import request from '@/utils/request'

//常量
const api_name = '/admin/system/sysUser'

export default {
    //列表
    getPageList(page,limit,searchObj) {
        return request({
            //接口路径
            url: `${api_name}/${page}/${limit}`,
            method: 'get', //提交方式
            //参数
            params: searchObj
        })
    },
    //添加
    save(user) {
        return request({
            //接口路径
            url: `${api_name}/save`,
            method: 'post', //提交方式
            //参数
            data: user
        })
    },
    //根据id查询
    getUserId(id) {
        return request({
            //接口路径
            url: `${api_name}/getUser/${id}`,
            method: 'get' //提交方式
        })
    },
    //修改
    update(user) {
        return request({
            //接口路径
            url: `${api_name}/update`,
            method: 'post', //提交方式
            //参数
            data: user  // 将结果转为list进行传递
        })
    },
    //删除
    removeById(id) {
        return request({
            //接口路径
            url: `${api_name}/remove/${id}`,
            method: 'delete' //提交方式
        })
    },
    //更改用户状态
    updateStatus(id,status) {
        return request({
            //接口路径
            url: `${api_name}/updateStatus/${id}/${status}`,
            method: 'get' //提交方式
        })
    },
}

禁用启用

在这里插入图片描述

 //更改用户状态
    switchStatus(row) {
      //判断,如果当前用户可用,修改禁用
      row.status = row.status === 1 ? 0 : 1
      api.updateStatus(row.id,row.status)
        .then(response => {
          this.$message.success(response.message || '操作成功')
          this.fetchData()
        })
    },


 <el-table-column prop="username" label="用户名" width="180"/>
      <el-table-column prop="name" label="姓名" width="110"/>
      <el-table-column prop="phone" label="手机" />
      <el-table-column label="状态" width="80">
        <template slot-scope="scope">
          <el-switch
            v-model="scope.row.status===1"
            @change="switchStatus(scope.row)">
          </el-switch>
        </template>
      </el-table-column>


 //更改用户状态
    updateStatus(id,status) {
        return request({
            //接口路径
            url: `${api_name}/updateStatus/${id}/${status}`,
            method: 'get' //提交方式
        })
    },

菜单管理

在这里插入图片描述
在这里插入图片描述

代码实现

当前节点下存在子节点使用递归的方式
在这里插入图片描述

在这里插入图片描述

import com.qwq.model.system.SysMenu;

import java.util.ArrayList;
import java.util.List;

public class MenuHelper {

    // 构建树形结构
    public static List<SysMenu> bulidTree(List<SysMenu> list) {
        List<SysMenu> trees = new ArrayList<>();
        for (SysMenu sysMenu : list) {
             //先得到根节点进行遍历
            if (sysMenu.getParentId().longValue() == 0) {
                trees.add(findChildren(sysMenu,list));
            }
        }
        return trees;
    }


    /**
     * 递归查找子节点
     * @param treeNodes
     * @return
     */
    public static SysMenu findChildren(SysMenu sysMenu, List<SysMenu> treeNodes) {
        sysMenu.setChildren(new ArrayList<SysMenu>());

        // sysMenu = 根节点    treeNodes = 全部数据集合

        //  遍历全部数据
        for (SysMenu it : treeNodes) {
            String id = sysMenu.getId();
            long ids = Long.parseLong(id);
            // 全部数据的ParentId
            Long parentId = it.getParentId();

            //  根节点 id == 遍历数据的parentId
            //  2 == 3  3 == 6
            if (ids == parentId) {
                System.out.println(ids +"============"+ it.getId());
                sysMenu.getChildren().add(findChildren(it ,  treeNodes));
            }
        }
        return sysMenu;
    }
}

权限管理

关于安全方面的两个核心功能是“认证”和“授权”,一般来说,Web 应用的安全性包括**用户认证(Authentication)和用户授权(Authorization)**两个部分,这两点也是 SpringSecurity 重要核心功能。

(1)用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码,系统通过校验用户名和密码来完成认证过程。

通俗点说就是系统认为用户是否能登录

(2)用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

通俗点讲就是系统判断用户是否有权限去做某些事情。

用户认证流程

在这里插入图片描述

添加登录日志

验证登录的拦截器登录成功后,调用service , request转化为ip , 进行新增处理
在这里插入图片描述

public class IpUtil {

    public static String getIpAddress(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    // 根据网卡取本机配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress="";
        }
        // ipAddress = this.getRequest().getRemoteAddr();

        return ipAddress;
    }

    public static String getGatwayIpAddress(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String ip = headers.getFirst("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress().getAddress().getHostAddress();
        }
        return ip;
    }
}

操作日志

在这里插入图片描述

后端打包

pom文件新增build标签


    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

在这里插入图片描述

<div id = ‘10’ / > 前端打包

在这里插入图片描述
输入命令进行打包
在这里插入图片描述
在这里插入图片描述

日期

格式:

<!--mapper的全限定类名-->
<mapper namespace="com.qwq.system.mapper.SysMenuMapper">


    <resultMap id="sysMenuMap" type="com.qwq.model.system.SysMenu" autoMapping="true">
    </resultMap>

    <!-- 用于select查询公用抽取的列 -->
    <sql id="columns">
      m.id,m.parent_id,m.name,m.type,m.path,m.component,m.perms,m.icon,m.sort_value,m.status,m.create_time,m.update_time,m.is_deleted
   </sql>


    <select id="findListByUserId" resultMap="sysMenuMap">
        select
        distinct <include refid="columns" />
        from sys_menu m
        inner join sys_role_menu rm on rm.menu_id = m.id
        inner join sys_user_role ur on ur.role_id = rm.role_id
        where
        ur.user_id = #{userId}
        and m.status = 1
        and rm.is_deleted = 0
        and ur.is_deleted = 0
        and  m.is_deleted = 0
    </select>

</mapper>

在这里插入图片描述

mybatis-plus的操作

在这里插入图片描述

相关文章:

  • 游戏网站制作模板/百度热搜榜排名昨日
  • 做视频在哪个网站找素材/关键词搜索广告
  • wordpress js版本号/台州seo排名外包
  • 丽江网页制作/合肥seo优化
  • 三栏wordpress模板下载/广州抖音推广公司
  • 网站业务流程设计/网站模板库官网
  • 6、Denoising Diffusion Probabilistic Models(扩散模型)
  • Linux操作系统进程状态Linux内核进程状态
  • Servlet 之 Responses
  • 如何写好JS
  • 【1813. 句子相似性 III】
  • dp解最长回文子串
  • 故障分析 | cassandra 集群数据故障转移
  • jvm系列(1)--JVM和Java体系架构
  • Openresty记录笔记
  • 最容易理解的并查集详解
  • Kruskal重构树学习笔记(C++)
  • 电商erp迁往云端必须注意的5件事