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 {
@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
}
@Overridepublic void destroy() {
}
@Overridepublic 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 {
@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
}
@Overridepublic void destroy() {
}
@Overridepublic 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 {
@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
}
@Overridepublic void destroy() {
}
@Overridepublic 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 {
@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
}
@Overridepublic void destroy() {
}
@Overridepublic 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 {
@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
}
@Overridepublic void destroy() {
}
@Overridepublic 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 {
@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
}
@Overridepublic void destroy() {
}
@Overridepublic 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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}@Overridepublic 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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}@Overridepublic 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')//如果有值 转成jsonif(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 {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1接收参数 转格式 封装对象String username = req.getParameter("username");String password = req.getParameter("password");//2调用serviceLoginService 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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//把类型转为子接口类型 方便调用http相关的内容HttpServletRequest req = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;// 读取到 /users /menusString 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();}}}
}
注意:
不同功能的过滤器 白名单配置的逻辑是不同的 需要单独考虑
