SpringBoot业务开发 09、Springboot集成token认证(一)

简介: SpringBoot业务开发 09、Springboot集成token认证(一)

一、引出session问题以及token鉴权


session问题


session出现的问题:


session都是保存在内存中,认证用户增多,服务端开销明显增大。

扩展性,若是认证的记录保存在某台服务器内存中时,意味着用户的下次请求只能够在该服务器内存中进行认证。对于分布式应用,限制了负载局衡的能力,意味着限制了引用扩展能力。

CSRF跨站攻击:由于session认证是基于浏览器发送请求携带指定cookie值到服务器来进行用户识别的,一旦cookie被截获或者说在其他网站点击了恶意链接用户就会很容易受到跨站请求伪造的攻击,恶意者可以通过某个用户的cookie来间接做一些额外的事情。


token鉴权机制


token的鉴权机制:http协议也是无状态的,不需要在服务端去保留用户的认证信息或者会话信息。这也就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录,为应用的扩展提供了遍历。


鉴权流程:简单来说就是服务器根据前端传来的用户名与密码生成token并返回前端,前端之后的请求都会携带该cookie来进行执行操作认证。


用户使用用户名密码来请求服务器。

服务器进行验证用户的信息。

服务器通过验证生成token发送给用户一个token。

客户端存储token,并在每次请求时附送上这个token值。

服务端验证token值,并返回数据。

注意:这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了Access-Control-Allow-Origin: *。



二、认识JWT(三部分详细构成)


2.1、JWT构成


JWT(JSON WEB TOKEN)是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串.


第一部分:头部(header)。

第二部分:载荷(payload),携带的信息。

第三部分:签证(signature)。

JWT字符串示例:JWT解析网站


eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ



第一部分:header


包含两部分信息:①声明类型,这里是jwt。②声明加密的算法 通常直接使用 HMAC SHA256。


完整的头部:


{
  'typ': 'JWT',
  'alg': 'HS256'
}


对头部进行加密:该加密是可以对称解密的


eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9



第二部分:playload


载荷就是存放有效信息的地方。携带的信息,这些有效信息包含三个部分:


标准中注册的声明


iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。


公共的声明:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密。


私有的声明:私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。


定义一个playload载荷:


{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}


进行base64加密,得到Jwt的第二部分:


eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9



第三部分:signature(签证)


签证信息由三部分组成:


header (base64后的)

payload (base64后的)

secret

第三部分组成:需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分


js加密示例:


// 将header与payload各自使用base64加密并用.来连接组合
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
// 接着将组合好之后的字符串进行加盐加密,使用HMACSHA256来进行加密
var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ


最终我们将header、playload以及signature各自的加密字符串使用.连接即可组成最终的JWT。


注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。



2.2、客户端实际应用token


客户端在接收到token之后再次发送请求时,一般是在请求头里加入Authorization,并加上Bearer标注:


fetch('api/user/1', {
  headers: {
    'Authorization': 'Bearer ' + token
  }
})


服务端会验证token,如果验证通过就会返回相应的资源。



2.3、JWT的大致流程



三、手写JWT


<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.10</version>
</dependency>


思路:头部、playload部分进行Base64编码,对于密钥部分是将playload与盐结合并使用MD5加密


import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONObject;
import java.util.Base64;
/**
 * @ClassName JWTUtils
 * @Author ChangLu
 * @Date 2021/9/20 13:58
 * @Description TODO
 */
public class JWTUtils {
    private static String secret = "jidjiof";
    public static void main(String[] args) {
        JSONObject header = new JSONObject();
        header.put("alg", "HS256");
        header.put("typ", "jwt");
        JSONObject playLoad = new JSONObject();
        playLoad.put("id", "123456");
        //头部与主体部分进行base64编码
        String base64Header = Base64.getEncoder().encodeToString(header.toJSONString().getBytes());
        String base64PlayLoad = Base64.getEncoder().encodeToString(playLoad.toJSONString().getBytes());
        //组合:其中第三部分是拿playLoad的json字符串与盐合并进行MD5加密
        String token = base64Header + "." + base64PlayLoad + "." + MD5.create().digestHex(playLoad.toJSONString() + secret);
        System.out.println("token:" + token);
        //解密
        String base64PlayLoadStr = new String(Base64.getDecoder().decode(token.split("\\.")[1]));//拿到playload编码前字符串
        String jwtSecret = token.split("\\.")[2];//拿取到MD5加密后密钥
        //判断是否有没有中途修改
        System.out.println(MD5.create().digestHex(base64PlayLoadStr + secret).equals(jwtSecret));
    }
}



对于我们自己实现的话还是有许多的不足之处,例如设置有效时间、相同的内容会产生相同的token等等。


有效时间:可以另外在playload中设置描述有效时间的属性值。

相同的内容产生不同的token字符串:可以在属性中添加一个时间戳,此时我们每次生成的都会不一样。

相关文章
|
7月前
|
XML 测试技术 API
利用C#开发ONVIF客户端和集成RTSP播放功能
利用C#开发ONVIF客户端和集成RTSP播放功能
4466 123
|
9月前
|
数据采集 运维 DataWorks
DataWorks 千万级任务调度与全链路集成开发治理赋能智能驾驶技术突破
智能驾驶数据预处理面临数据孤岛、任务爆炸与开发运维一体化三大挑战。DataWorks提供一站式的解决方案,支持千万级任务调度、多源数据集成及全链路数据开发,助力智能驾驶模型数据处理与模型训练高效落地。
|
监控 Java API
1K star!这个开源项目让短信集成简单到离谱,开发效率直接翻倍!
SMS4J 是一款由国内技术团队打造的短信聚合框架,专为解决多短信服务商接入难题而生。它就像短信界的"瑞士军刀",目前已整合21家主流短信服务商,从阿里云、腾讯云到中国移动云MAS,开发者只需通过简单配置即可实现多平台无缝切换。
863 4
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
635 0
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
956 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
10月前
|
监控 安全 Java
Java 开发中基于 Spring Boot 3.2 框架集成 MQTT 5.0 协议实现消息推送与订阅功能的技术方案解析
本文介绍基于Spring Boot 3.2集成MQTT 5.0的消息推送与订阅技术方案,涵盖核心技术栈选型(Spring Boot、Eclipse Paho、HiveMQ)、项目搭建与配置、消息发布与订阅服务实现,以及在智能家居控制系统中的应用实例。同时,详细探讨了安全增强(TLS/SSL)、性能优化(异步处理与背压控制)、测试监控及生产环境部署方案,为构建高可用、高性能的消息通信系统提供全面指导。附资源下载链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
2225 0
|
人工智能 程序员 测试技术
通义灵码与魔搭 Notebook 深度集成:在线编码开箱即用,开发效率倍增
通义灵码 2.0 AI 程序员 2025 年 1 月正式上线,目前已经服务百万开发者,成为国内开发者最受欢迎的智能编码助手。
|
Java 应用服务中间件 Scala
Spring Boot 实现通用 Auth 认证的 4 种方式
本文介绍了在Spring Boot中实现通用Auth的四种方式:传统AOP、拦截器(Interceptor)、参数解析器(ArgumentResolver)和过滤器(Filter)。每种方式都通过实例代码详细说明了实现步骤,并总结了它们的执行顺序。首先,Filter作为Servlet规范的一部分最先被调用;接着是Interceptor,它可以在Controller方法执行前后进行处理;然后是ArgumentResolver,在参数传递给Controller之前解析并验证参数
330 1
|
人工智能 IDE 测试技术
通义灵码与魔搭Notebook深度集成:在线编码开箱即用,开发效率倍增
通义灵码2.0 AI程序员于2025年1月上线,目前已支持超过百万开发者。该工具的智能编程能力现已与阿里云AI模型开发平台魔搭ModelScope实现技术集成
583 0
|
XML JavaScript Java
SpringBoot集成Shiro权限+Jwt认证
本文主要描述如何快速基于SpringBoot 2.5.X版本集成Shiro+JWT框架,让大家快速实现无状态登陆和接口权限认证主体框架,具体业务细节未实现,大家按照实际项目补充。
976 11