SpringBoot中过滤器Filter+JWT令牌实现登录验证

 更新时间:2024年04月19日 09:59:59   作者:.徐十三.  
本文主要介绍了SpringBoot中过滤器Filter+JWT令牌实现登录验证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

登录校验-Filter

分析

过滤器Filter的快速入门以及使用细节我们已经介绍完了,接下来最后一步,我们需要使用过滤器Filter来完成案例当中的登录校验功能。

在这里插入图片描述

我们先来回顾下前面分析过的登录校验的基本流程:

  • 要进入到后台管理系统,我们必须先完成登录操作,此时就需要访问登录接口login。

  • 登录成功之后,我们会在服务端生成一个JWT令牌,并且把JWT令牌返回给前端,前端会将JWT令牌存储下来。

  • 在后续的每一次请求当中,都会将JWT令牌携带到服务端,请求到达服务端之后,要想去访问对应的业务功能,此时我们必须先要校验令牌的有效性。

  • 对于校验令牌的这一块操作,我们使用登录校验的过滤器,在过滤器当中来校验令牌的有效性。如果令牌是无效的,就响应一个错误的信息,也不会再去放行访问对应的资源了。如果令牌存在,并且它是有效的,此时就会放行去访问对应的web资源,执行相应的业务操作。

大概清楚了在Filter过滤器的实现步骤了,那在正式开发登录校验过滤器之前,我们思考两个问题:

  • 所有的请求,拦截到了之后,都需要校验令牌吗?

    • 答案:登录请求例外
  • 拦截到请求后,什么情况下才可以放行,执行业务操作?

    • 答案:有令牌,且令牌校验通过(合法);否则都返回未登录错误结果

具体流程

我们要完成登录校验,主要是利用Filter过滤器实现,而Filter过滤器的流程步骤:

在这里插入图片描述

基于上面的业务流程,我们分析出具体的操作步骤:

  • 获取请求url
  • 判断请求url中是否包含login,如果包含,说明是登录操作,放行
  • 获取请求头中的令牌(token)
  • 判断令牌是否存在,如果不存在,返回错误结果(未登录)
  • 解析token,如果解析失败,返回错误结果(未登录)
  • 放行

代码实现

分析清楚了以上的问题后,我们就参照接口文档来开发登录功能了,登录接口描述如下:

请求参数

参数格式:application/json

参数说明:

名称类型是否必须备注
usernamestring必须用户名
passwordstring必须密码

请求数据样例:

{
	"username": "jinyong",
    "password": "123456"
}

响应数据

参数格式:application/json

参数说明:

名称类型是否必须默认值备注其他信息
codenumber必须响应码, 1 成功 ; 0 失败
msgstring非必须提示信息
datastring必须返回的数据 , jwt令牌

响应数据样例:

{
  "code": 1,
  "msg": "success",
  "data": "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6YeR5bq4IiwiaWQiOjEsInVzZXJuYW1lIjoiamlueW9uZyIsImV4cCI6MTY2MjIwNzA0OH0.KkUc_CXJZJ8Dd063eImx4H9Ojfrr6XMJ-yVzaWCVZCo"
}

备注说明

用户登录成功后,系统会自动下发JWT令牌,然后在后续的每次请求中,都需要在请求头header中携带到服务端,请求头的名称为 token ,值为 登录时下发的JWT令牌。

如果检测到用户未登录,则会返回如下固定错误信息:

{
	"code": 0,
	"msg": "NOT_LOGIN",
	"data": null
}

登录校验过滤器:LoginCheckFilter

@Slf4j
@WebFilter(urlPatterns = "/*") //拦截所有请求
public class LoginCheckFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        //前置:强制转换为http协议的请求对象、响应对象 (转换原因:要使用子类中特有方法)
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //1.获取请求url
        String url = request.getRequestURL().toString();
        log.info("请求路径:{}", url); //请求路径:http://localhost:8080/login


        //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行
        if(url.contains("/login")){
            chain.doFilter(request, response);//放行请求
            return;//结束当前方法的执行
        }


        //3.获取请求头中的令牌(token)
        String token = request.getHeader("token");
        log.info("从请求头中获取的令牌:{}",token);


        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if(!StringUtils.hasLength(token)){
            log.info("Token不存在");

            Result responseResult = Result.error("NOT_LOGIN");
            //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            String json = JSONObject.toJSONString(responseResult);
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);

            return;
        }

        //5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(token);
        }catch (Exception e){
            log.info("令牌解析失败!");

            Result responseResult = Result.error("NOT_LOGIN");
            //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            String json = JSONObject.toJSONString(responseResult);
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);

            return;
        }


        //6.放行
        chain.doFilter(request, response);

    }
}

JWT导入的maven依赖

<!--JWT令牌-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

JWT的工具类

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;

public class JwtUtils {

    private static String signKey = "shisan";
    private static Long expire = 43200000L;

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map<String, Object> claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}

在上述过滤器的功能实现中,我们使用到了一个第三方json处理的工具包fastjson。我们要想使用,需要引入如下依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

登录校验的过滤器我们编写完成了,接下来我们就可以重新启动服务来做一个测试:

测试前先把之前所编写的测试使用的过滤器,暂时注释掉。直接将@WebFilter注解给注释掉即可。

测试1:未登录是否可以访问部门管理页面

首先关闭浏览器,重新打开浏览器,在地址栏中输入:http://localhost:9528/#/system/dept

由于用户没有登录,登录校验过滤器返回错误信息,前端页面根据返回的错误信息结果,自动跳转到登录页面了

在这里插入图片描述

测试2:先进行登录操作,再访问部门管理页面

登录校验成功之后,可以正常访问相关业务操作页面

在这里插入图片描述

总结: 这个过滤器检查请求的URL是否包含 “login”。如果包含,则直接允许请求继续。如果不包含 “login”,则检查JWT令牌的存在和有效性。如果令牌不存在或无效,返回一个JSON格式的 “NOT_LOGIN” 错误响应。如果令牌存在并且有效,则允许请求继续。

到此这篇关于SpringBoot-过滤器Filter+JWT令牌实现登录验证的文章就介绍到这了,更多相关SpringBoot 登录验证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MyBatis-plus更新对象时将字段值更新为null的实现方式

    MyBatis-plus更新对象时将字段值更新为null的实现方式

    mybatis-plus在执行更新操作,当更新字段为 空字符串 或者 null 的则不会执行更新,如果要将指定字段更新null,可以通过以下三种方式实现,感兴趣的小伙伴跟着小编一起来看看吧
    2023-10-10
  • java中的数组初始化赋初值方式

    java中的数组初始化赋初值方式

    这篇文章主要介绍了java中的数组初始化赋初值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • spring-security关于hasRole的坑及解决

    spring-security关于hasRole的坑及解决

    这篇文章主要介绍了spring-security关于hasRole的坑及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • java实现简单的拼图游戏

    java实现简单的拼图游戏

    这篇文章主要为大家详细介绍了java实现简单的拼图游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Java抽象类原理与用法实例详解

    Java抽象类原理与用法实例详解

    这篇文章主要介绍了Java抽象类原理与用法,结合实例形式详细分析了Java抽象类相关概念、原理、定义、使用方法及操作注意事项,需要的朋友可以参考下
    2019-11-11
  • Java中的同步非阻塞IO模型详解

    Java中的同步非阻塞IO模型详解

    这篇文章主要介绍了Java中的同步非阻塞IO模型详解,同步非阻塞IO模型,我们能够知道,用户线程一直发送请求,内核一直都能都够返回 ,直到内核完成准备数据、数据拷贝的工作,并且返回成功的指示,在此过程中用户线程不是阻塞的状态,需要的朋友可以参考下
    2024-01-01
  • 10中java常见字符串操作实例

    10中java常见字符串操作实例

    给大家分享10中java常见字符串操作方法以及相关实例代码,对此有需要的读者们可以学习参考下。
    2019-07-07
  • Mybatis Mapper接口工作原理实例解析

    Mybatis Mapper接口工作原理实例解析

    这篇文章主要介绍了Mybatis Mapper接口工作原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java NIO缓冲区Buffer基础教程示例

    Java NIO缓冲区Buffer基础教程示例

    这篇文章主要介绍了Java NIO缓冲区Buffer基础教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Spring Boot整合Swagger2的完整步骤详解

    Spring Boot整合Swagger2的完整步骤详解

    这篇文章主要给大家介绍了关于Spring Boot整合Swagger2的完整步骤,文中通过示例代码将整合的步骤一步步介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07

最新评论