【JavaEE】—— JWT+Filter过滤器、Interceptor拦截器实现登录校验(拦截请求)

需求

在后端管理系统中,需要登录后才能访问后端系统页面,没有登录则跳转到登录页面进行登录,那么如何对用户请求做校验、如何拦截非法请求?

一、JWT令牌

JWT(JSON Web Token)是一个简单的字符串,可以在请求参数或者是请求头当中直接传递。可以在jwt令牌中存储用户的相关信息,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。

JWT由三部分组成:

**第一部分:**记录令牌类型、签名算法。

**第二部分:**有效载荷。即用户相关的数据

**第三部分:**签名算法。防止token被篡改,对前两部分根据指定密钥进行加密。

实现登录校验的基本流程

1、要进入到后台管理系统,首先完成登录操作,登录成功后,服务端生成一个JWT令牌,并且返回给前端,前端将JWT令牌存储到本地。

2、在后续的每次请求中,前端都会将JWT令牌传到服务端,服务端的拦截器会对请求进行拦截,

拦截需要考虑到各种情况:登录页面不需要拦截

3、然后校验令牌的有效性,如果无效,则返回一个错误信息不放行请求,并跳转到登录页面,校验成功后,放行请求,跳转到后台页面。

1、引入jwt依赖

XML 复制代码
<!-- JWT依赖-->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2、jwt工具类

application.yml

XML 复制代码
jwt:
  secret: zxyzxyzxy
  timeout: 60

工具类

有两个方法,一个方法生成token,另一个方法校验token

java 复制代码
@Component
public class JWTUtil {

    //指定签名密钥
    @Value("${jwt.secret}")
    private String jwtSecret;

    //指定过期时间
    @Value("${jwt.timeout}")
    private long timeout;

    public String generateJWT(Map<String,Object> claims){
        //加密令牌
        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256,jwtSecret)//签名算法,不能太短
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis()+1000 * 60 * timeout))//过期时间为60分钟
                .compact();//生成

        return jwt;
    }

    public Map<String,Object> parseJWT(String jwt){
        //返回有效载荷信息
        Claims claims = Jwts.parser()
                .setSigningKey(jwtSecret)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}

3、使用jwt生成token

java 复制代码
             //设置jwt令牌
            //存储有效载荷(用户信息)
            Map<String,Object> map = new HashMap<>();
            map.put("id",loginInfo.getId());
            map.put("username",loginInfo.getUsername());
            //生成token
            String jwt = jwtUtil.generateJWT(map);
            loginInfo.setToken(jwt);

二、过滤器

过滤器位于客户端和Servlet之间,可以拦截整个Web应用的所有请求 。

1、定义过滤器

  • doFilter方法:这个方法是在每一次拦截到请求之后都会被调用,所以这个方法是会被调用多次的,每拦截到一次请求就会调用一次doFilter()方法。

  • @WebFilter,并指定属性urlPatterns,通过这个属性指定过滤器要拦截哪些请求,/*表示拦截所有请求

java 复制代码
@Slf4j
@Component
@WebFilter(urlPatterns = "/*")
public class LoginFilter implements Filter {

    @Autowired
    private JWTUtil jwtUtil;
    
    //拦截到请求时,调用该方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String url = request.getRequestURI();//请求地址
        log.info("请求地址:" + url);

        //如果是登录请求直接放行
        if(url.equals("/login")){
            filterChain.doFilter(request, response);//放行
            return;
        }

        //拦截其他请求,判断token
        String token = request.getHeader("token");
        if(token == null){
            response.setStatus(401);
            return;
        }

        try {
            //解析token
            Map<String, Object> map = jwtUtil.parseJWT(token);
            log.info(map.get("username") + "登录");
            filterChain.doFilter(request, response);
        }catch (Exception e){
            response.setStatus(401);
        }

    }
}

2、启动类开启对Servlet的支持

java 复制代码
@ServletComponentScan //开启对Servlet组件的支持
@SpringBootApplication
public class TliasManagementApplication {
    public static void main(String[] args) {
        SpringApplication.run(TliasManagementApplication.class, args);
    }
}

三、拦截器(第二种拦截方式)

过滤器和拦截器选择一种使用即可。

拦截器位于Servlet和控制器之间,是SpringMVC提供的,用于拦截Spring环境的请求 ,拦截器属于SpringMVC,依赖于Spring容器 。

1、定义拦截器

java 复制代码
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private JWTUtil jwtUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();//获取请求地址
        //login地址在webmvc过滤
        //拦截其他请求
        String token = request.getHeader("token");
        if(token == null){
            response.setStatus(401);
            return false;
        }
        //判断token是否有效
        try {
            Map<String, Object> stringObjectMap = jwtUtil.parseJWT(token);
            return true;
        }catch (Exception e){
            response.setStatus(401);
            return false;
        }
    }
}

2、注册配置拦截器

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截所有请求,放行/login请求
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}
相关推荐
期待のcode2 小时前
MyBatisX插件
java·数据库·后端·mybatis·springboot
醇氧4 小时前
【Windows】优雅启动:解析一个 Java 服务的后台启动脚本
java·开发语言·windows
serendipity_hky4 小时前
【SpringCloud | 第4篇】Gateway网关统一入口
spring·spring cloud·微服务·gateway
sunxunyong4 小时前
doris运维命令
java·运维·数据库
菜鸟起航ing4 小时前
Spring AI 全方位指南:从基础入门到高级实战
java·人工智能·spring
古城小栈5 小时前
Docker 多阶段构建:Go_Java 镜像瘦身运动
java·docker·golang
MapGIS技术支持5 小时前
MapGIS Objects Java计算一个三维点到平面的距离
java·开发语言·平面·制图·mapgis
Coder_Boy_5 小时前
业务导向型技术日志首日记录(业务中使用的技术栈)
java·驱动开发·微服务
盖世英雄酱581366 小时前
springboot 项目 从jdk 8 升级到jdk21 会面临哪些问题
java·后端
济南壹软网络科技有限公司6 小时前
企业级盲盒系统:Java高并发架构在多元化抽奖电商中的设计与实践
java·架构·开源源码·盲盒源码·盲盒h5·盲盒app