一、、验证过滤器进行权限验证的原理。
- 拦截请求:
- 当客户端发送一个请求到服务器时,过滤器会首先捕获到这个请求。
- 过滤器并不直接处理请求,而是对请求进行预处理。
- 检查权限:
- 在过滤器中,会根据预设的规则或逻辑对请求进行权限检查。
- 这可能涉及到检查请求的某些属性,如IP地址、用户凭证(如用户名和密码)、令牌(如JWT)等。
- 如果请求符合预设的权限要求,则过滤器会允许请求继续传递;否则,过滤器会拦截请求,并可能返回错误响应或重定向到登录页面等。
- 传递请求:
- 如果请求通过了权限检查,过滤器会通过
chain.doFilter()
方法将请求传递给下一个过滤器或目标资源(如servlet或MVC控制器)。 - 在这个过程中,过滤器可能会修改请求的属性或添加额外的信息到请求中,以便后续的处理。
- 如果请求通过了权限检查,过滤器会通过
- 处理响应:
- 当目标资源处理完请求并返回响应时,过滤器会再次捕获到这个响应。
- 过滤器可以在返回给客户端之前对响应进行后处理,如修改响应头、添加额外的数据等。
- 过滤器链:
- 在一个web应用中,可能会有多个过滤器按照特定的顺序组成过滤器链。
- 每个过滤器都会按照配置的顺序对请求进行拦截和处理。
- 请求会依次经过每个过滤器,直到到达目标资源;响应也会依次经过每个过滤器,直到返回给客户端。
- 配置顺序:
- 过滤器的执行顺序与它们在配置文件(如web.xml)中的配置顺序相关。
- 开发者可以根据需要调整过滤器的顺序,以确保它们按照预期的方式工作。
- 类型与用途:
- 过滤器有多种类型,如授权过滤器、资源过滤器、操作过滤器、异常过滤器和结果过滤器等。
- 每种类型的过滤器都有其特定的用途和场景,开发者可以根据实际需求选择合适的过滤器类型。
二、将自己之前的项目,加上过滤器验证功能。
LoginCheckFilter
package com.caz.filter;
import com.alibaba.fastjson.JSONObject;
import com.caz.pojo.Result;
import com.caz.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
//路径匹配器,支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
private boolean isStaticResource(String requestURI) {
// 静态资源目录列表
List<String> staticResourcePatterns = Arrays.asList(
"/img/", "/css/", "/js/", "/fonts/", "/images/", "/favicon.ico"
// 可以根据需要添加更多静态资源目录
);
// 遍历静态资源目录列表,检查请求URI是否以这些目录开头
for (String pattern : staticResourcePatterns) {
if (requestURI.startsWith(pattern)) {
return true; // 如果找到匹配的目录,则返回true
}
}
// 如果没有找到匹配的目录,则返回false
return false;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、获取本次请求的URL
String requestURI = request.getRequestURI();// /backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/loginJwt",
"/logout",
"/login/**",
"/login.html",
"/film.html",
"/error.html",
"/films/**",
};
// 检查请求URI是否为静态资源
if (isStaticResource(requestURI)) {
filterChain.doFilter(request, response); // 静态资源,跳过验证
return;
}
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3、如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
//3.获取请求头中的令牌(token)
String token = request.getHeader("token");
log.info("从请求头中获取的令牌:{}",token);
if(!StringUtils.hasLength(token)){
log.info("Token不存在");
Result responseResult = Result.error("Token不存在");
//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
String json = JSONObject.toJSONString(responseResult);
response.setContentType("application/json;charset=utf8");
//响应
response.getWriter().write(json);
return;
}
//5.解析token,如果解析失败,返回错误结果(未登录)
try {
JwtUtils.parseJWT(token);
}catch (Exception e){
log.info("令牌解析失败!");
Result responseResult = Result.error("令牌解析失败!");
//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
String json = JSONObject.toJSONString(responseResult);
response.setContentType("application/json;charset=utf8");
//响应
response.getWriter().write(json);
return;
}
//6.放行
filterChain.doFilter(request, response);
}
/**
* 路径匹配,检查本次请求是否需要放行
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if(match){
return true;
}
}
return false;
}
}
FilmController
package com.caz.controller;
import com.caz.pojo.Film;
import com.caz.pojo.PageBean;
import com.caz.pojo.Result;
import com.caz.service.FilmService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@RequestMapping("/films")
public class FilmController {
@Autowired
private FilmService filmService;
//查询所有数据
@GetMapping("/{page}/{pageSize}")
public Result page(
@PathVariable Integer page,
@PathVariable Integer pageSize,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "director", required = false) String director,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate
) {
// 记录日志
log.info("分页查询,参数:page={}, pageSize={}, name={}, director={}, startDate={}, endDate={}",
page, pageSize, name, director, startDate, endDate);
// 调用业务层分页查询功能
// 直接传递startDate和endDate字符串(如果业务层可以处理)
PageBean pageBean = filmService.list_chaxun(page, pageSize, name, director, startDate, endDate);
// 响应
return Result.success(pageBean);
}
//删除信息
@DeleteMapping("/delete/{id}")
public Result delete(@PathVariable("id") Integer id) {
log.info("根据id删除:{}", id);
filmService.delete(id);
return Result.success();
}
//查询回显
@GetMapping("/edit/{id}")
public Result getById(@PathVariable Integer id) {
log.info("根据id查询信息:{}", id);
Film film = filmService.getById(id);
return Result.success(film);
}
//更新信息
@PutMapping("/update")
public Result update(@RequestBody Film film) {
log.info("更新电影信息:{}", film);
filmService.update(film);
return Result.success();
}
@PostMapping("insert")
public Result insertFilm(@RequestBody Film film) {
boolean result = filmService.insertFilm(film);
if (result) {
// 成功 code==1
return Result.success();
} else {
// 失败 code==0
return Result.error("添加失败");
}
}
}
LoginController
package com.caz.controller;
import com.caz.pojo.Manager;
import com.caz.pojo.PageBean;
import com.caz.pojo.Result;
import com.caz.service.ManagerService;
import com.caz.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
public class LoginController {
@Autowired
private ManagerService managerService;
@PostMapping("/login")
/*public Result login(HttpServletRequest httpServletRequest, @RequestBody Manager manager) {
// 尝试使用提供的manager信息进行登录
Manager loggedInManager = managerService.login(manager);
// 如果登录成功,loggedInManager将不为null
if (loggedInManager != null) {
// 登录成功,将用户名保存到session中
httpServletRequest.getSession().setAttribute("username", loggedInManager.getUsername());
// 可选:获取并打印session中的用户名,以验证设置成功
String username = (String) httpServletRequest.getSession().getAttribute("username");
System.out.println("登录成功,用户名:" + username);
// 返回成功的结果
return Result.success();
} else {
// 登录失败,返回错误信息
System.out.println("登录失败,用户名或密码错误");
return Result.error("用户名或密码错误");
}
}*/
public Result login(@RequestBody Manager manager) {
//调用业务层:登录功能
Manager loginManager = managerService.login(manager);
//判断:登录用户是否存在
if(loginManager !=null ){
//自定义信息
Map<String , Object> claims = new HashMap<>();
claims.put("id", loginManager.getId());
claims.put("password",loginManager.getPassword());
claims.put("username",loginManager.getUsername());
//使用JWT工具类,生成身份令牌
String token = JwtUtils.generateJwt(claims);
System.out.println(token);
Map<String, String> response = new HashMap<>();
response.put("token", token);
return Result.success(token);
}
return Result.error("用户名或密码错误");
}
@GetMapping("/logout")
public Result logout(HttpServletRequest request) {
//清理Session中保存的当前登录管理员的id
request.getSession().removeAttribute("managers");
return Result.success("退出成功");
}
@GetMapping("/film")
public Result film() {
PageBean l=managerService.list2(1,20);
return Result.success(l);
}
}
FilmMapper
package com.caz.mapper;
import com.caz.pojo.Film;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface FilmMapper {
List<Film> list();
List<Film> list_chaxun(@Param("name") String name, @Param("director") String director, @Param("startDate") String startDate, @Param("endDate") String endDate);
//根据id删除
void deleteById(Integer id);
Film getById(Integer id);
void update(Film film);
int insert(Film film);
}
ManagerMapper
package com.caz.mapper;
import com.caz.pojo.Film;
import com.caz.pojo.Manager;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ManagerMapper {
Manager getByUsernameAndPassword(Manager manager);
List<Film> list2();
}
FilmService
package com.caz.service;
import com.caz.pojo.Film;
import com.caz.pojo.PageBean;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public interface FilmService {
PageBean list(Integer page, Integer pageSize);
//分页查询
PageBean list_chaxun(Integer page, Integer pageSize, String name, String director, String startDate, String endDate);
//删除数据
void delete(Integer id);
Film getById(Integer id);
void update(Film film);
boolean insertFilm(Film film);
}
FilmServiceImpl
package com.caz.service.impl;
import com.caz.mapper.FilmMapper;
import com.caz.pojo.Film;
import com.caz.pojo.PageBean;
import com.caz.service.FilmService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class FilmServiceImpl implements FilmService {
@Autowired
private FilmMapper filmMapper;
@Override
public PageBean list(Integer page, Integer pageSize) {
// 设置分页参数
PageHelper.startPage(page, pageSize);
// 执行分页查询
List<Film> filmList = filmMapper.list();
// System.out.println(poetList);
// 获取分页结果
PageInfo<Film> p = new PageInfo<>(filmList);
//封装PageBean
PageBean pageBean = new PageBean(p.getTotal(), p.getList());
return pageBean;
}
@Override
public PageBean list_chaxun(Integer page,Integer pageSize,String name,String director, String startDate, String endDate) {
// 设置分页参数
PageHelper.startPage(page, pageSize);
// 执行分页查询
List<Film> filmList = filmMapper.list_chaxun(name,director,startDate,endDate);
// 获取分页结果
PageInfo<Film> p = new PageInfo<>(filmList);
//封装PageBean
PageBean pageBean = new PageBean(p.getTotal(), p.getList());
return pageBean;
}
@Override
public void delete(Integer id){
filmMapper.deleteById(id);
}
@Override
public Film getById(Integer id){
return filmMapper.getById(id);
}
@Override
public void update(Film film) {
filmMapper.update(film);
}
@Override
public boolean insertFilm(Film film) {
int result = filmMapper.insert(film);
return result == 1;
}
}
ManagerService
package com.caz.service;
import com.caz.pojo.Manager;
import com.caz.pojo.PageBean;
public interface ManagerService {
Manager login(Manager manager);
PageBean list2(Integer page, Integer pageSize);
}
ManagerServiceImpl
package com.caz.service.impl;
import com.caz.mapper.ManagerMapper;
import com.caz.pojo.Film;
import com.caz.pojo.Manager;
import com.caz.pojo.PageBean;
import com.caz.service.ManagerService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ManagerServiceImpl implements ManagerService {
@Autowired
private ManagerMapper managerMapper;
@Override
public Manager login(Manager manager){
return managerMapper.getByUsernameAndPassword(manager);
}
@Override
public PageBean list2(Integer page, Integer pageSize) {
// 设置分页参数
PageHelper.startPage(page, pageSize);
// 执行分页查询
List<Film> List = managerMapper.list2();
// 获取分页结果
PageInfo<Film> p = new PageInfo<>(List);
//封装PageBean
PageBean pageBean = new PageBean(p.getTotal(), p.getList());
return pageBean;
}
}
FilmMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.caz.mapper.FilmMapper">
<!-- 查询 -->
<select id="list" resultType="com.caz.pojo.Film">
select *
from film
</select>
<!-- 条件分页查询 -->
<select id="list_chaxun" resultType="com.caz.pojo.Film">
SELECT * FROM film
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="director != null and director != ''">
AND director LIKE CONCAT('%', #{director}, '%')
</if>
<if test="startDate != null and endDate != null">
AND `date` BETWEEN #{startDate} AND #{endDate}
</if>
</where>
</select>
<!--根据id删除-->
<delete id="deleteById" parameterType="java.lang.Integer">
delete
from film
where id = #{id}
</delete>
<select id="getById" resultType="com.caz.pojo.Film">
select * from film
<where>
id= #{id}
</where>
</select>
<update id="update">
update film
<set>
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="date != null">
`date` = #{date,jdbcType=DATE},
</if>
<if test="director != null and director != ''">
director = #{director},
</if>
<if test="actor != null and actor != ''">
actor = #{actor},
</if>
<if test="style != null and style != ''">
style = #{style},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
</set>
where id = #{id}
</update>
<insert id="insert">
INSERT INTO film (id, name, date, director, actor, style, description)
VALUES (#{id}, #{name}, #{date}, #{director}, #{actor}, #{style}, #{description})
</insert>
</mapper>
ManagerMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.caz.mapper.ManagerMapper">
<select id="getByUsernameAndPassword" resultType="com.caz.pojo.Manager">
select * from manager where username=#{username} and password=#{password}
</select>
<!-- 查询 -->
<select id="list2" resultType="com.caz.pojo.Film">
select *
from film
</select>
</mapper>
实现界面
三、Apifox的使用
四、Git的继续使用