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

发布于:2024-12-18 ⋅ 阅读:(107) ⋅ 点赞:(0)

需求

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

一、JWT令牌

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

JWT由三部分组成:

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

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

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

实现登录校验的基本流程

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

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

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

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

1、引入jwt依赖

<!-- JWT依赖-->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2、jwt工具类

application.yml

jwt:
  secret: zxyzxyzxy
  timeout: 60

工具类

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

@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

             //设置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,通过这个属性指定过滤器要拦截哪些请求,/*表示拦截所有请求

@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的支持

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

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

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

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

1、定义拦截器

@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、注册配置拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截所有请求,放行/login请求
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到