您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页登录认证 (一)JWT令牌

登录认证 (一)JWT令牌

来源:华佗小知识

 1、登录功能

        登录功能的核心是:接收前端请求传递的用户名和密码 ,再根据用户名查询密码并且和前端传递的密码做以比较,如果相同,则说明用户输入的用户名和密码正确。如果出现查询不到用户名或密码不一致,则说明用户输入的用户名或密码错误。

2、登录校验

2.1、问题分析

        但是此做法会出现一个问题我们在浏览器直接输入别的页面网址,页面可以直接进来,登录功能就没有达到我们想要的效果,所以我们需要去添加登录校验,如下图。

        看完以上我们在宏观上对登录有一个认知了,众所周知http协议是无状态的,所谓无状态指的是每次请求都是的,下一次请求并不会携带上次请求的数据,在实现登录以后,接下来操作中,服务器也不知道用户到底登录了没有,因为http请求是无状态的,所以无法判断,所以我们要采取在用户登录后存储一个标识,在接下来接口方法执行之前,先判断用户是否登录,如果没有登录,返回前端让重新登录就好了。

具体应该怎么来实现呢?一共涉及到web开发中的两个技术:

1、会话技术

        (1)cookie

        (2)session

        (3)令牌技术(主要讲解)

2、统一拦截技术

        (1)Servlet规范中的Filter过滤器

        (2)Spring提供的interceptor

下面我们先学习会话技术。

2.2、会话技术

2.2.1、会话技术介绍

        会话字面意思就是谈话、交谈,在web开发中,浏览器与服务器之间的一次连接我们就称为一次会话。

                举个例子,我们打开浏览器访问服务器资源(浏览器不能关,服务器不能断)

                第一次:访问登录接口

                第二次:访问药品接口

                第三次:访问员工接口

        只要浏览器不关,以上三次请求属于一次会话中完成的。

        听完这些我们对会话技术有了一定的了解,接下来我们在了解一下会话跟踪。

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

会话跟踪技术有两种:

1、Cookie(客户端会话跟踪技术)

        数据存储在客户端浏览器

2、Session(服务端会话跟踪技术)

        数据存储在服务端

2.2.2、会话跟踪方案
2.2.2.1、Cookie

        Cookie 是客户端会话跟踪技术,它是存储在客户端浏览器的,我们使用 Cookie 来跟踪会话,我们就可以在浏览器第一次发起请求来请求服务器的时候,我们在服务器端来设置一个Cookie。

        用户登录厚设置一个Cookie,我们在Cookie中存一些数据。服务器端在给客户端在响应数据的时候,会自动的将 Cookie 响应给浏览器,浏览器接收到响应回来的 Cookie 之后,会自动的将 Cookie 的值存储在浏览器本地。接下来在后续的每一次请求当中,都会将浏览器本地所存储的 Cookie 自动地携带到服务端。

优缺点

优点:http协议中支持的技术,Set-Cookie 响应头的解析和cookie数据的携带,都是浏览器自动的,无需手动操作

缺点:

        1、移动端APP无法使用

        2、不安全、用户可以在浏览器自己禁用Cookie

        3、Cookie不能跨域

2.2.2.2、Session

        Session是服务器端会话跟踪技术,所以它是存储在服务器端的,Session 的底层其实就是基于我们刚才所介绍的 Cookie 来实现的。

        浏览器在第一次请求服务器时,我们直接在服务器中回去会话对象Session,第一次请求Session,会话对象不存在,这时服务器会自动创建一个session,每一个Session都有一个ID,在接下来服务器响应浏览器时,将session的id通过cookie响应给浏览器,相当于在响应头中增加了一个Set-Cookie响应头,Cookie的名字是固定的JSESSIONID代表服务器端会话对象的Session的ID,浏览器会自动识别响应头,然后将Cookie存储在浏览器本地。接下来没词请求中,都会将Cookie数据获取出来并携带到服务端接下来服务器拿到JSESSIONID这个 Cookie 的值,也就是 Session 的ID。拿到 ID 之后,就会从众多的 Session 当中来找到当前请求对应的会话对象Session。

优缺点

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

缺点:

        1、服务器集群环境下无法直接使用Session

        2、移动端APP中无法使用Cookie

        3、用户可以自己禁用Cookie

        4、Cookie不能跨域

以上两种传统会话技术存在很多问题,,为了解决以上问题,在现在企业级开发当中,我们都会使用第三种方案,令牌技术。

2.3、令牌技术

2.3.1、介绍

令牌技术其本质就是一个字符串。令牌有很多种,我们使用的是JWT令牌。

JWT全称:JSON Web Token  (官网:https://jwt.io/)

JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)

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

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

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

JWT令牌最典型的应用场景就是登录认证:

        1. 在浏览器发起请求来执行登录操作,此时会访问登录的接口,如果登录成功之后,我们需要生成一个jwt令牌,将生成的 jwt令牌返回给前端。
        2. 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。
        3. 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处理。

JWT在整个流程中涉及到两部操作,分别是生成和校验。

2.3.2、生成和校验

首先我们先来实现JWT令牌的生成。要想使用JWT令牌,需要先引入JWT的依赖:

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

生成JWT代码实现:

/**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘钥
     * @param secretKey jwt秘钥
     * @param ttlMillis jwt过期时间(毫秒)
     * @param claims    设置的信息
     * @return
     */
public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
        // 指定签名的时候使用的签名算法,也就是header那部分
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 生成JWT的时间
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置过期时间
                .setExpiration(exp);

        return builder.compact();
    }

实现了JWT令牌的生成,下面我们接着使用Java代码来校验JWT令牌(解析生成的令牌):

 /**
     * Token解密
     *
     * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
     * @param token     加密后的token
     * @return
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置需要解析的jwt
                .parseClaimsJws(token)
                .getBody();
        return claims;
    }

我们在使用JWT令牌时需要注意:

        JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的。

        如果JWT令牌解析校验时报错,则说明 JWT令牌被篡改 或 失效了,令牌非法。

令牌技术进行会话跟踪: 

        在登录时,如果登录成功,我们就可以生成一个令牌,令牌就是用户的合法身份凭证。接下来我们在响应数据的时候,我们就可以直接将令牌响应给前端。在前端程序当中接收到令牌之后,就需要将这个令牌存储起来。这个存储可以存储在 cookie 当中,也可以存储在其他的存储空间(比如:localStorage)当中。最后在后续的每一次请求当中,都需要将令牌携带到服务端。携带到服务端之后,接下来我们就需要来校验令牌的有效性。如果令牌是有效的,就说明用户已经执行了登录操作,如果令牌是无效的,就说明用户之前并未执行登录操作。

        此时,如果是在同一次会话的多次请求之间,我们想共享数据,我们就可以将共享的数据存储在令牌当中就可以了。

优缺点

优点:

        1、支持pc端、移动端

        2、解决集群环境下的认证问题

        3、减轻服务器的存储压力

缺点:需要自己实现(包括令牌的生成、令牌的传递、令牌的校验)

现在企业开发当中使用的最多的就是令牌技术进行会话跟踪。而前面的这两种传统的方案,现在企业项目开发当中已经很少使用了。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务