【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");
    }
}
相关推荐
IUGEI1 小时前
从原理到落地:DAG在大数据SLA中的应用
java·大数据·数据结构·后端·算法
Whisper_Sy7 小时前
Flutter for OpenHarmony移动数据使用监管助手App实战 - 网络状态实现
android·java·开发语言·javascript·网络·flutter·php
乂爻yiyao8 小时前
1.1 JVM 内存区域划分
java·jvm
没有bug.的程序员9 小时前
Spring Cloud Eureka:注册中心高可用配置与故障转移实战
java·spring·spring cloud·eureka·注册中心
CryptoRzz9 小时前
如何高效接入日本股市实时数据?StockTV API 对接实战指南
java·python·kafka·区块链·状态模式·百度小程序
码农水水9 小时前
中国邮政Java面试被问:容器镜像的多阶段构建和优化
java·linux·开发语言·数据库·mysql·面试·php
若鱼19199 小时前
SpringBoot4.0新特性-BeanRegistrar
java·spring
好好研究10 小时前
SpringBoot - yml配置文件
java·spring boot·spring
学海无涯书山有路10 小时前
Android FragmentContainerView 新手详解(Java 版)
android·java·开发语言
XiYang-DING11 小时前
【Java SE】数据类型、变量、类型转换、运算符以及程序逻辑控制
java·开发语言