day20_权限控制

day20_权限控制

1filter简介

2过滤器实例

1过滤器通过请求地址 进入调用链
package com.javasm.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * @className: MyFilter
 * @author: gfs
 * @date: 2025/10/28 9:55
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/listArea")
public class MyFilter implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
​
    }
​
    @Override
    public void destroy() {
​
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //相当于servlet中的service 请求地址匹配到会自动执行
        System.out.println("/filter1 going......");
        //调用链继续向后执行
        filterChain.doFilter(servletRequest,servletResponse);
​
    }
}
​
2多层过滤器配置
/*
* 如果使用了多层过滤
* 自动形成过滤器链 规则跟配置方式有关
* 1注解方式 根据包名 类名顺序排列 调用顺序 (特例 特殊包名类会倒着加载)
*  测试一下 包名+类名是否符合需要的顺序
*
* 2配置文件方式  从上到下加载 写在上边的先运行 下边的后运行
*
* */
package com.javasm.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * @className: MyFilter
 * @author: gfs
 * @date: 2025/10/28 9:55
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/listArea")
public class MyFilter implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
​
    }
​
    @Override
    public void destroy() {
​
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //相当于servlet中的service 请求地址匹配到会自动执行
        System.out.println("/filter1 going......");
        //调用链继续向后执行
        filterChain.doFilter(servletRequest,servletResponse);
​
        /*
        * 如果使用了多层过滤
        * 自动形成过滤器链 规则跟配置方式有关
        * 1注解方式 根据包名 类名顺序排列 调用顺序 (特例 特殊包名类会倒着加载)
        *  测试一下 包名+类名是否符合需要的顺序
        *
        * 2配置文件方式  从上到下加载 写在上边的先运行 下边的后运行
        *
        * */
    }
}
​
package com.javasm.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * @className: MyFilter
 * @author: gfs
 * @date: 2025/10/28 9:55
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/listArea")
public class MyFilter2 implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
​
    }
​
    @Override
    public void destroy() {
​
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //相当于servlet中的service 请求地址匹配到会自动执行
        System.out.println("/filter2 going......");
        //调用链继续向后执行
        filterChain.doFilter(servletRequest,servletResponse);
​
    }
}
​
3通过通配符* 扩大请求进入的范围
/*
* 使用通配符 扩大请求进入范围
* 1精确匹配servlet
*  /user/*
   /menus/*
​
   可以对两个模块同时生效
   过滤器 /serv/*     servlet   /serv/user/*
                               /serv/menus/*
   只对一个模块生效
   过滤器 /serv/user/*
​
  2全局匹配servlet
  /* 所有请求都进入
     根据请求路径 排除掉一些请求 不走过滤器的判断逻辑
*
* 
* */

对某个servlet生效

package com.javasm.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * @className: MyFilter
 * @author: gfs
 * @date: 2025/10/28 9:55
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/serv/listArea/*")
public class MyFilter2 implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
​
    }
​
    @Override
    public void destroy() {
​
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //相当于servlet中的service 请求地址匹配到会自动执行
        System.out.println("/filter2 going......");
        //调用链继续向后执行
        filterChain.doFilter(servletRequest,servletResponse);
​
    }
}
​

对多个servlet生效

package com.javasm.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * @className: MyFilter
 * @author: gfs
 * @date: 2025/10/28 9:55
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/serv/*")
public class MyFilter2 implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
​
    }
​
    @Override
    public void destroy() {
​
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //相当于servlet中的service 请求地址匹配到会自动执行
        System.out.println("/filter2 going......");
        //调用链继续向后执行
        filterChain.doFilter(servletRequest,servletResponse);
​
    }
}
​

对全局生效

package com.javasm.filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
/**
 * @className: MyFilter
 * @author: gfs
 * @date: 2025/10/28 9:55
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/*")
public class MyFilter2 implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
​
    }
​
    @Override
    public void destroy() {
​
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //相当于servlet中的service 请求地址匹配到会自动执行
        System.out.println("/filter2 going......");
        //调用链继续向后执行
        filterChain.doFilter(servletRequest,servletResponse);
​
    }
}
​

3项目中加入过滤器 做公共功能

1请求编码 跨域过滤器
package com.javasm.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @className: MyFilter1
 * @author: gfs
 * @date: 2025/10/28 10:39
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/*")
public class MyFilter1 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //把类型转为子接口类型 方便调用http相关的内容
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        //请求参数公共配置
        servletRequest.setCharacterEncoding("utf-8");
        //跨域配置
        /* 允许跨域的主机地址*/
        resp.setHeader("Access-Control-Allow-Origin", "http://localhost:5173");
        /* 允许跨域的请求⽅法GET, POST, HEAD 等*/
        resp.setHeader("Access-Control-Allow-Methods", "*");

        /*重新预检验跨域的缓存时间*/
        resp.setHeader("Access-Control-Max-Age", "3600");
        /* 允许跨域的请求头 */
        resp.setHeader("Access-Control-Allow-Headers", "*");
        /* 是否携带cookie */
        resp.setHeader("Access-Control-Allow-Credentials", "true");

        //不要轻易设置
        //resp.setContentType("application/json;charset=utf-8");

        filterChain.doFilter(servletRequest,servletResponse);


    }
}
2权限控制过滤器

登录访问控制过滤器

package com.javasm.filter;

import com.alibaba.fastjson.JSON;
import com.javasm.entity.AdminUser;
import com.javasm.entity.ReturnCode;
import com.javasm.entity.ReturnResult;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @className: MyFilter2
 * @author: gfs
 * @date: 2025/10/28 10:49
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/*")
public class MyFilter2 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //把类型转为子接口类型 方便调用http相关的内容
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        //做权限控制
        //登录访问控制
        HttpSession session = req.getSession();
        AdminUser loginUser =(AdminUser) session.getAttribute("loginUser");

        String requestURI = req.getRequestURI();
        String servletPath = req.getServletPath();
        System.out.println(requestURI);
        System.out.println(servletPath);
        //白名单 (特权)
        if("/login".equals(servletPath)){
            filterChain.doFilter(req,resp);
        }else{
            if(loginUser!=null){
                //登录过 继续执行要访问的服务
                filterChain.doFilter(req,resp);
            }else{
                ReturnResult returnResult = new ReturnResult(ReturnCode.NOT_LOGIN.getCode(),ReturnCode.NOT_LOGIN.getMsg());
                //输出json数据
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                writer.print(JSON.toJSONString(returnResult));
                writer.close();
            }
        }






    }
}

前端 需要根据后端数据做适配

axios中增加响应拦截器 如果接收到没有登录的响应码 跳转到登录页面

import axios from 'axios'
import router from '@/router'
//技术的二次封装

//可以有公共的请求url协议 地址 路径
//如果路径中给的是带协议的完整路径 优先走完整路径
axios.defaults.baseURL = 'http://localhost:8080/baseProj';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
//跨域时发送cookie 为了使用session
axios.defaults.withCredentials = true
//无session模式 自己传请求头里 放票据信息  后端自己存缓存 自己判断


// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    if(response.data.code == 10020){
        router.push("/login")
        return
    }
    return response;
  }, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
  });


//使用二次封装的get post请求
const myPost = (currentURL,params)=>{
     // 发起一个post请求
        return axios({
            method: 'post',
            url: currentURL,
            data: params
        });
}

const myGet = (currentURL,params)=>{

    return axios({
            method: 'get',
            url: currentURL,
            params: params
        });

}


export {axios,myPost,myGet};

主页面中 检查是否有登录的标记 如果没有跳转到登录页面

top.vue

<script setup>
import { ref,onMounted } from 'vue' 
import { User, Histogram, SwitchButton } from '@element-plus/icons-vue'
import router from '@/router'
import {axios,myPost,myGet} from '@/axios/myAxios.js'
import { ElMessage,ElMessageBox  } from 'element-plus';


const username = ref('')

onMounted(()=>{
    //从sessionStorage中获取登录用户
    let loginUserStr = sessionStorage.getItem('loginUser')
    //如果有值 转成json
    if(loginUserStr){
        //显示到登录的用户名中
        let lignUser = JSON.parse(loginUserStr)
        username.value = lignUser.username
    }else{
        //判断是否有登录标记 没哟 跳转到登录
        router.push('/login')
    }
   
})

const logout = async()=>{
    //清除sessionStorage中的登录用户
    sessionStorage.removeItem('loginUser')
    //清后端数据
    let resp = await myGet("/logout");
    ElMessage.info(resp.data.msg)
    //跳转到登录页面
    router.push('/login')
}


</script>

<template>
    <el-row justify="end">
        <el-col style="font-size: 30px;color: gray;" :span="12">XXXX管理系统</el-col>
        <el-col  :span="8">
            <el-button-group >
                <el-button type="primary" color="#DDD" :icon="User" >{{username}}</el-button>
                <el-button type="primary" color="#DDD" :icon="Histogram" />
                <el-button type="primary" color="#CCC" :icon="SwitchButton" @click="logout" />
            </el-button-group>
        </el-col>
    </el-row>
</template>

<style scoped></style>
3模块权限

动态菜单只能限制没有界面 但是不能限制直接访问接口 所以需要通过过滤器做限制

登录时 读取该用户可访问的url列表 存入缓存

package com.javasm.controller;

import com.alibaba.fastjson.JSON;
import com.javasm.entity.AdminMenu;
import com.javasm.entity.AdminUser;
import com.javasm.entity.ReturnCode;
import com.javasm.entity.ReturnResult;
import com.javasm.service.LoginService;
import com.javasm.service.impl.LoginServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;

/**
 * @className: LoginServlet
 * @author: gfs
 * @date: 2025/10/23 14:43
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1接收参数 转格式 封装对象
        String username = req.getParameter("username");
        String password = req.getParameter("password");

       //2调用service
        LoginService loginService = new LoginServiceImpl();
        //开始检查信息是否符合要求
        AdminUser loginUser = loginService.getUserByName(username);

        //3根据结果 反馈数据
        ReturnResult rr = new ReturnResult();
        if(loginUser!=null){
            if(loginUser.getIsvalid() == 1){
                if(loginUser.getPassword().equals(password)){
                    //登录成功 .....
                    //1.把登录用户存入session 为后续流程缓存用户数据
                    HttpSession session = req.getSession();
                    session.setAttribute("loginUser",loginUser);
                    //2.更新最后登录时间
                    loginService.updateLoginTime(loginUser.getUid());
                    //3.查询当前用户的菜单信息
                    List<AdminMenu> listMenuByUid = loginService.listMenuByUid(loginUser.getUid());
                    //4.查询当前用户可访问url列表 存入后端缓存
                    List<String> userUrl = loginService.listUrlByUid(loginUser.getUid());
                    session.setAttribute("userUrl",userUrl);
                    //5.返回操作成功信息
                    rr.setCode(ReturnCode.LOGIN_SUCCESS.getCode());
                    rr.setMsg(ReturnCode.LOGIN_SUCCESS.getMsg());
                    //如果有关联 通过对象关联体现数据关系
                    loginUser.setUserMenu(listMenuByUid);
                    //如果没关联 建自定义map存放不同类别的数据
//                    HashMap<String, Object> returnMap = new HashMap<>();
//                    returnMap.put("loginUser",loginUser);
//                    returnMap.put("userMenu",listMenuByUid);
//                    rr.setReturnData(returnMap);
                    rr.setReturnData(loginUser);
                }else{
                    //密码不对
                    rr.setCode(ReturnCode.LOGIN_FAILED1.getCode());
                    rr.setMsg(ReturnCode.LOGIN_FAILED1.getMsg());
                }
            }else{
                //用户已离职
                rr.setCode(ReturnCode.LOGIN_FAILED2.getCode());
                rr.setMsg(ReturnCode.LOGIN_FAILED2.getMsg());
            }


        }else{
            //用户名找不到
            rr.setCode(ReturnCode.LOGIN_FAILED1.getCode());
            rr.setMsg(ReturnCode.LOGIN_FAILED1.getMsg());
        }
        //输出json数据
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print(JSON.toJSONString(rr));
        writer.close();
    }
}

在过滤器中判断当次请求是否在可访问列表中

package com.javasm.filter;

import com.alibaba.fastjson.JSON;
import com.javasm.entity.ReturnCode;
import com.javasm.entity.ReturnResult;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * @className: MyFilter1
 * @author: gfs
 * @date: 2025/10/28 10:39
 * @version: 0.1
 * @since: jdk17
 * @description:
 */
@WebFilter("/*")
public class MyFilter3 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //把类型转为子接口类型 方便调用http相关的内容
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        // 读取到 /users  /menus
        String servletPath = req.getServletPath();
        HttpSession session = req.getSession();
        List<String> userUrl =(List<String>) session.getAttribute("userUrl");
        //配置白名单
        //系统中不需要单独配置 默认每个用户都会有的功能
        //上传头像 静态资源 html css js 图片 视频 声音
        if("/login".equals(servletPath)||"/logout".equals(servletPath)||servletPath.endsWith(".png")||servletPath.endsWith(".jpg")||servletPath.endsWith(".gif")){
            filterChain.doFilter(req,resp);
        }else{
            //查集合中是否有指定元素
            if(userUrl.contains(servletPath)){
                //有权限
                filterChain.doFilter(req,resp);
            }else{
                //没权限
                ReturnResult returnResult = new ReturnResult(ReturnCode.LOGIN_NO_POMISSION.getCode(),ReturnCode.LOGIN_NO_POMISSION.getMsg());
                //输出json数据
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                writer.print(JSON.toJSONString(returnResult));
                writer.close();
            }
        }




    }
}

注意:

不同功能的过滤器 白名单配置的逻辑是不同的 需要单独考虑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值