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

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 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字符串:可以在属性中添加一个时间戳,此时我们每次生成的都会不一样。

相关文章
|
16天前
|
JavaScript 前端开发 持续交付
Prettier 高级应用:集成 CI/CD 流水线与插件开发
【10月更文挑战第18天】Prettier 是一款流行的代码格式化工具,它能够自动将代码格式化成一致的风格,从而提高代码的可读性和维护性。对于希望进一步发挥 Prettier 潜力的高级用户而言,将 Prettier 集成到持续集成(CI)和持续部署(CD)流程中,确保每次提交的代码都符合团队标准,是非常重要的。此外,通过开发自定义插件来支持更多语言或扩展 Prettier 的功能也是值得探索的方向。本文将详细介绍这两方面的内容。
35 2
|
26天前
|
安全 Java 数据库
安全无忧!在 Spring Boot 3.3 中轻松实现 TOTP 双因素认证
【10月更文挑战第8天】在现代应用程序开发中,安全性是一个不可忽视的重要环节。随着技术的发展,双因素认证(2FA)已经成为增强应用安全性的重要手段之一。本文将详细介绍如何在 Spring Boot 3.3 中实现基于时间的一次性密码(TOTP)双因素认证,让你的应用安全无忧。
59 5
|
1月前
|
安全 Java 关系型数据库
springboot整合springsecurity,从数据库中认证
本文介绍了如何在SpringBoot应用中整合Spring Security,并从数据库中进行用户认证的完整步骤,包括依赖配置、数据库表创建、用户实体和仓库接口、用户详情服务类、安全配置类、控制器类以及数据库初始化器的实现。
84 3
springboot整合springsecurity,从数据库中认证
|
10天前
|
JSON Java API
springboot集成ElasticSearch使用completion实现补全功能
springboot集成ElasticSearch使用completion实现补全功能
17 1
|
26天前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
47 1
|
27天前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
22 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
22天前
|
Dart Android开发
鸿蒙Flutter实战:03-鸿蒙Flutter开发中集成Webview
本文介绍了在OpenHarmony平台上集成WebView的两种方法:一是使用第三方库`flutter_inappwebview`,通过配置pubspec.lock文件实现;二是编写原生ArkTS代码,自定义PlatformView,涉及创建入口能力、注册视图工厂、处理方法调用及页面构建等步骤。
41 0
|
26天前
|
Java Spring
springboot 学习十一:Spring Boot 优雅的集成 Lombok
这篇文章是关于如何在Spring Boot项目中集成Lombok,以简化JavaBean的编写,避免冗余代码,并提供了相关的配置步骤和常用注解的介绍。
75 0
|
26天前
|
开发框架 监控 搜索推荐
GoFly快速开发框架集成ZincSearch全文搜索引擎 - Elasticsearch轻量级替代为ZincSearch全文搜索引擎
本文介绍了在项目开发中使用ZincSearch作为全文搜索引擎的优势,包括其轻量级、易于安装和使用、资源占用低等特点,以及如何在GoFly快速开发框架中集成和使用ZincSearch,提供了详细的开发文档和实例代码,帮助开发者高效地实现搜索功能。
108 0
|
Java 应用服务中间件 Maven
传统maven项目和现在spring boot项目的区别
Spring Boot:传统 Web 项目与采用 Spring Boot 项目区别
483 0
传统maven项目和现在spring boot项目的区别