当前位置: 首页 > news >正文

Java学习--JWT令牌

https://jwt.io/

为了防止在未登录情况下,用户也能查看信息,我们引入会话跟踪

会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。

会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。

一、客户端会话跟踪技术:Cookie

优点:HTTP协议中支持的技术

缺点: 移动端APP无法使用Cookie;不安全,用户可以自己禁用Cookie;Cookie不能跨域

二、服务端会话跟踪技术:Session

优点:存储在服务端,安全

缺点:服务器集群环境下无法直接使用Session;Cookie的缺点

三、令牌技术

优点:支持PC端、移动端;解决集群环境下的认证问题;减轻服务器端存储压力

缺点:需要自己实现



3.1 JWT

定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。

组成:

第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{"alg":"HS256","type":"JWT"}

第二部分:Payload(有效载荷)携带一些自定义信息默认信息等。 例如:{"id":"1","username":"Tom"}

第三部分:Signature(签名),防止Token被篡改、确保安全性。将headerpayload,并加入指定秘钥,通过指定签名算法计算而来。

3.2 JWT生成

引入依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

记得引入:

<dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

登录成功返回jwt

@PostMapping("/login")
    public Result login(@RequestBody Emp emp){

        log.info("员工登录:{}",emp);
        Emp e = empService.login(emp);

        //生成令牌
        if(e != null ){
            Map<String, Object> claims = new HashMap<>();
            claims.put("id",e.getId());
            claims.put("name",e.getName());
            claims.put("username",e.getUsername());
            String jwt = JwtUtils.generateJwt(claims);

            return Result.success(jwt);
        }

        return Result.error("用户名或密码错误");

    }

浏览器会存储jwt,往后每次请求都会加上jwt;

3.3 过滤器Filter

3.3.1概念

Filter 过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。

过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。

过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。

3.3.2 配置Filter

1.定义Filter:定义一个类,实现 Filter 接口,并重写其所有方法。

2.配置FilterFilter类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加 @ServletComponentScan 开启Servlet组件支

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


    @Override//初始化方法,只调用一次
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override//拦截到请求之后调用,调用多次
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("拦截到请求");

        //发行操作

        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override//销毁方法,只调用一次
    public void destroy() {
        Filter.super.destroy();
    }
}
@ServletComponentScan//开启了对servlet组件支持
@SpringBootApplication
public class SpringbootMybatisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootMybatisApplication.class, args);
    }

}

3.3.3 过滤器链

一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链

3.3.4 登录校验

代码实现如下:

使用fastJson将字符串转换为Json格式,注意配置

  <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.76</version>
  </dependency>
 @Override//拦截到请求之后调用,调用多次
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("拦截到请求");
        HttpServletRequest req = (HttpServletRequest)servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        //1.获取请求url
        String url = req.getRequestURL().toString();
        log.info("请求的url:{}",url);

        //2.判断请求url是否含login,如果包含,放行
        if(url.contains("login")){
            log.info("登录操作,放行。。。");
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }

        //3.获取请求头中的令牌token
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在,不存在的时候
        if(!StringUtils.hasLength(jwt)){
            log.info("请求头token为空,返回未登录信息");
            Result error = Result.error("NOT_LOGIN");
            //将对象转换成json
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }

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

            Result error = Result.error("NOT_LOGIN");
            //将对象转换成json
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }
        //6.令牌合法放行
        log.info("令牌合法放行");
        filterChain.doFilter(servletRequest,servletResponse);
    }

3.4 拦截器(Interceptor)

3.4.1 概念

概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。

作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。

3.4.2 注册拦截器

1.定义拦截器,实现HandlerInterceptor接口,并重写其所有方法。

2.注册拦截器

拦截器可以根据需求,配置不同的拦截路径

3.4.3 登录校验

@Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        

        //1.获取请求url
        String url = req.getRequestURL().toString();
        log.info("请求的url:{}",url);

        //2.判断请求url是否含login,如果包含,放行
        if(url.contains("login")){
            log.info("登录操作,放行。。。");
            return true;
        }

        //3.获取请求头中的令牌token
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在,不存在的时候
        if(!StringUtils.hasLength(jwt)){
            log.info("请求头token为空,返回未登录信息");
            Result error = Result.error("NOT_LOGIN");
            //将对象转换成json
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return false;
        }

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

            Result error = Result.error("NOT_LOGIN");
            //将对象转换成json
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return false;
        }
        //6.令牌合法放行
        log.info("令牌合法放行");
      
        return HandlerInterceptor.super.preHandle(req, resp, handler);
    }

相关文章:

  • LLM - 使用 Unsloth 框架 轻量级 训练 GRPO 算法 教程
  • cursor+deepseek实现完整的俄罗斯方块小游戏
  • ES 聚合查询
  • 数据安全的守护者:备份文件的重要性及自动化备份策略
  • 自学嵌入式第28天-----select,
  • BambuStudio学习笔记:MarchingSquares类
  • mysql中如何保证没有幻读发生
  • 道可云人工智能每日资讯|亚马逊云业务部门成立智能体人工智能团队
  • 解析调控网络之竞争结合
  • 只要四行代码就能解决mac上运行exe文件的问题
  • 05-2基于vs2022的c语言笔记——表达式
  • Mysql-经典故障案例(1)-主从同步由于主键问题引发的故障
  • 深度学习Save Best、Early Stop
  • Quadrotor-NMPC-Control 开源项目复现与问题记录
  • 03.06 QT
  • ComfyUI进阶教程核心要点与详解
  • 多模态模型在做选择题时,如何设置Prompt,如何精准定位我们需要的选项
  • 【Kubernetes 指南】基础入门——Kubernetes 基本概念(四)
  • Python在DevOps中的应用:自动化CI/CD管道的实现
  • 【电控笔记z29】扰动估测器DOB估测惯量J-摩擦系数B
  • 目前做网站的好处/企业专业搜索引擎优化
  • 如何建设好英文网站/seo收费标准多少
  • 新闻有哪些网站有哪些类型/东莞seo网站排名优化公司
  • 网站设计毕业论文的模板咋写/seo网络推广企业
  • wordpress 图片对其/seo推广岗位职责
  • 南宁网站推广公司/大数据培训机构排名前十