首页 > 其他分享 >springsecurity 使用浅谈(一)

springsecurity 使用浅谈(一)

时间:2024-01-05 23:56:20浏览次数:32  
标签:令牌 浅谈 JWT 用户 认证 使用 服务器 springsecurity 请求

1. 背景

  springsecurity框架主要用于Web应用的认证和授权。所谓认证就是验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户。而授权就是经过认证后判断当前用户是否有权

限进行某个操作。认证和授权也是SpringSecurity作为安全框架的核心功能。

2. 前置知识

在传统的项目中,我们通常使用会话技术来保存用户信息并进行用户认证。会话是客户端和服务器之间连续的请求和响应过程,用于保持用户的状态信息。然而,HTTP协议本身是无状态的,服务器无法直接识别每个请求的来源,因此需要一种机制来标识和关联请求。

在会话管理中,有两种常见的实现方式:session(会话)和cookie(Cookie)。Session通过在服务器端记录信息来确定用户身份和状态,但这会增加服务器的存储压力。当客户端浏览器访问服务器时,服务器会在服务器端创建一个会话,并为该会话分配一个唯一的标识符,即sessionID。服务器将sessionID发送给客户端浏览器,通常通过设置一个名为"sessionID"的Cookie,将其存储在浏览器中。

一旦客户端浏览器保存了该Cookie,它会在后续的请求中自动发送给服务器,从而实现会话的持续。服务器通过sessionID可以在服务器端找到对应的会话数据,并根据其中的用户状态进行处理。如果浏览器禁用了Cookie,也可以通过URL重写的方式将sessionID作为查询参数发送给服务器。

另一方面,Cookie是服务器在HTTP响应中附带的一个小型文本文件,它存储在客户端浏览器中。一旦浏览器保存了某个Cookie,它会在后续的请求中自动将该Cookie发送给服务器。通过在Cookie中存储一些用户标识或其他数据,服务器可以在不使用session的情况下实现状态保持和用户认证。

最近,使用基于令牌(token)的身份验证方式逐渐流行起来,逐渐取代了传统的session和cookie方式。令牌是一种加密的字符串,它包含了与用户相关的信息,并可以通过在每个请求的头部或参数中携带令牌来实现身份验证。与session和cookie不同,令牌不需要在服务器端存储用户状态,这降低了服务器的存储压力,并且可以更好地支持分布式系统和跨域访问。

总结一下,传统的会话管理中使用了session和cookie来实现用户认证和状态保持。Session通过在服务器端记录信息,而cookie则是在客户端浏览器中存储会话标识符。然而,随着基于令牌的身份验证方式的兴起,令牌逐渐取代了session和cookie,提供了更灵活和可扩展的身份验证机制。令牌通过在请求中携带加密的字符串来验证用户身份,不需要在服务器端存储状态信息,从而提供了更好的性能和安全性。

Session的弊端包括以下几点:

  1. 服务器压力增大:通常情况下,Session是存储在服务器的内存中的,每个用户认证通过后,其Session数据都会保存在服务器的内存中。当用户数量增大时,服务器的内存压力也会增大。

  2. CSRF跨站伪造请求攻击:Session通常是基于Cookie进行用户识别的,如果Cookie被截获,用户容易受到跨站请求伪造(CSRF)攻击。即使不使用Cookie,而是通过URL重写方式发送SessionID,也容易被截获敏感信息。

  3. 扩展性不强:在多个服务器部署的情况下,如果用户登录到一台服务器A上,而下次访问另一台服务器B,B上并没有A的Session信息。为了解决这个问题,需要将Session保存到数据库中,这增加了服务器的存储压力。

相比之下,Token是一种令牌,由服务端生成的加密字符串,作为客户端请求的标识。当用户登录后,服务器生成一个Token并返回给客户端浏览器,以后客户端只需携带这个Token进行请求即可,无需再次携带用户名和密码。

浏览器将接收到的Token存储在本地存储(Local Storage)中。当浏览器再次访问服务器时,服务器对浏览器传来的Token进行解密,并进行用户数据查询。如果查询成功,则认证通过,实现状态保持。因此,即使有多台服务器,服务器只需解密Token和查询用户数据,而无需在服务器端保存用户的认证信息或会话信息。这就为应用的扩展提供了便利,同时也减少了服务器的存储压力。Token的出现解决了Session的弊端,成为Session的替代品。

JWT

  JWT其实就是一种被广泛使用的token,它的全称是JSON Web Token,它通过数字签名的方式,以JSON对象为载体,在不同的服务终端之间安全地传输信息。

  JWT最常见的使用场景就是授权认证,一旦用户登录,后续每个请求都将包含JWT,系统在每次处理用户请求之前,都要先进行JWT安全校验,通过之后再进行处理。

JWT由三部分组成,它们通过点号(.)进行分隔:

  1. Header(头部):包含了令牌的类型(即JWT)和所使用的签名算法(例如HMAC、RSA等)。
    示例:{"alg": "HS256", "typ": "JWT"}

  2. Payload(负载):包含了一些声明信息,用于在令牌中传递有关用户或其他实体的信息。声明分为三种类型:注册声明(Registered Claims)、公共声明(Public Claims)和私有声明(Private Claims)。注册声明是一组预定义的声明,例如iss(签发者)、exp(过期时间)等。公共声明是自定义的声明,但建议遵循一些已定义的命名规范。私有声明是用户自定义的声明,用于满足应用程序的特定需求。
    示例:{"sub": "user123", "name": "John Doe", "admin": true}

  3. Signature(签名):使用密钥对Header和Payload进行签名,以验证令牌的完整性和真实性。签名可以防止令牌被篡改或伪造。签名通常使用密钥和指定的签名算法进行计算。
    示例:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

JWT的工作流程如下:

  1. 用户通过提供有效的凭据(如用户名和密码)进行认证。

  2. 服务器验证凭据,并生成一个JWT。

  3. 服务器将JWT作为响应的一部分返回给客户端。

  4. 客户端将JWT保存在本地,通常存储在Local Storage或Session Storage中。

  5. 客户端在后续的请求中将JWT作为身份验证凭据进行发送。

  6. 服务器接收到请求后,通过验证JWT的签名和有效性来验证用户身份。

  7. 如果JWT验证成功,服务器使用其中的信息来处理请求。

JWT具有以下优点:

    1. 无需在服务器端存储会话信息:JWT是基于令牌的认证机制,服务器不需要在存储中保存会话信息,从而提高了可扩展性。

    2. 跨域支持:由于JWT是通过在请求中携带令牌进行验证,因此可以轻松支持跨域请求。

    3. 自包含性:JWT中包含了所有必要的信息,因此服务器不需要在数据库中进行查询,从而提高了性能。

    4. 可扩展性:JWT的负载中可以包含自定义的声明,以满足应用程序的特定需求。

3. springsecurity原理

Spring Security的核心原理是基于过滤器链(Filter Chain)的工作机制。当一个请求进入应用程序时,Spring Security会通过一系列的过滤器来处理该请求,进行认证和授权操作。

下面是Spring Security的一般工作流程:

 

  1. 客户端发送请求到应用程序,请求被Spring Security的过滤器链拦截。

  2. 过滤器链中的第一个过滤器是UsernamePasswordAuthenticationFilter,它负责处理基于用户名和密码的认证请求。如果请求携带了用户名和密码,该过滤器将尝试对用户进行认证。

  3. 认证过程中,Spring Security使用AuthenticationManager来进行实际的认证操作。AuthenticationManager是一个接口,用于管理不同的认证提供者(Authentication Provider)。

  4. 认证提供者根据请求中的用户名和密码,从用户存储(如数据库)中获取用户信息,并进行密码匹配验证。如果验证成功,认证提供者将返回一个Authentication对象,其中包含了用户的身份信息和权限信息。

  5. 如果认证成功,UsernamePasswordAuthenticationFilter会调用AuthenticationSuccessHandler来处理认证成功的逻辑,例如生成并返回一个令牌(如JWT),或者重定向到某个页面。

  6. 如果认证失败,UsernamePasswordAuthenticationFilter会调用AuthenticationFailureHandler来处理认证失败的逻辑,例如返回一个错误消息或重定向到登录页面。

  7. 认证成功后,请求继续经过过滤器链的其他过滤器,例如CsrfFilter用于防止跨站请求伪造攻击,CorsFilter用于处理跨域资源共享。

  8. 在请求到达受保护的资源时,Spring Security会使用AccessDecisionManager来进行授权判断。AccessDecisionManager是一个接口,用于根据用户的身份和权限信息,决定是否允许访问该资源。

  9. 如果用户被授权访问资源,请求将被传递到相应的控制器或处理器进行处理。

3. springsecurity 认证流程

 

在Spring Security中,认证流程涉及多个组件和步骤,主要包括以下几个关键步骤:

  1. 用户发送认证请求:用户在应用程序的登录页面输入用户名和密码,并发送认证请求。

  2. 过滤器链拦截请求:Spring Security的过滤器链拦截认证请求,拦截器链中的第一个过滤器是UsernamePasswordAuthenticationFilter,它负责处理基于用户名和密码的认证请求。

  3. AuthenticationManager处理认证:UsernamePasswordAuthenticationFilter将认证请求交给AuthenticationManager处理。AuthenticationManager是Spring Security的认证管理器,负责实际的认证操作。

  4. 获取用户信息:认证管理器使用UserDetailsService来获取用户信息。UserDetailsService是一个接口,定义了获取用户信息的方法。它可以从数据库、LDAP、内存或其他数据源中获取用户信息。

  5. 构建Authentication对象:认证管理器根据获取到的用户信息,构建一个Authentication对象,其中包含了用户的身份信息和权限信息。

  6. 进行密码匹配验证:认证管理器会使用PasswordEncoder接口来进行密码匹配验证。PasswordEncoder是一个接口,定义了密码加密和验证的方法。它用于比较用户输入的密码和存储的密码是否匹配。

  7. 认证成功:如果密码匹配验证成功,认证管理器将返回一个经过认证的Authentication对象。

  8. AuthenticationProvider处理认证结果:认证管理器会将认证结果传递给AuthenticationProvider进行进一步处理。AuthenticationProvider是一个接口,定义了对认证结果的处理方法。

  9. 调用认证成功处理器或认证失败处理器:根据认证结果,AuthenticationProvider将调用相应的认证成功处理器(AuthenticationSuccessHandler)或认证失败处理器(AuthenticationFailureHandler)。

  10. 认证成功处理:如果认证成功,认证成功处理器将根据配置的策略执行相应的操作,如生成并返回令牌(如JWT)或重定向到指定页面。

  11. 认证失败处理:如果认证失败,认证失败处理器将根据配置的策略执行相应的操作,如返回错误消息或重定向到登录页面。

4. springsecurity 自定义实现思路

当访问某个业务接口时,会被Security的login接口拦截,但是如果我们不想使用Security默认的登录页面,那么怎么办呢,还有,springsecurity的校验,默认是从内存中查找,而我们希望是根据数据库来做校验,那么怎么实现呢。根据上边的认证流程图可知,我们需要从不满足我们需求的地方去重新实现其方法,按照我们需求实现:

【登录】

①、自定义登录接口。然后自己去调用ProviderManager的方法进行认证 如果认证通过生成jwt,然后把用户信息存入redis中,从而实现无状态的会话管理和快速的用户信息访问。

②、自定义UserDetailsService接口的实现类。在这个实现类中自己重写相应方法,方法去查询数据库,来做校验

【校验】

①、定义Jwt认证过滤器。用于获取token,然后解析token获取其中的userid,还需要从redis中获取用户信息,然后存入SecurityContextHolder。SecurityContextHolder是Spring Security提供的一个类,用于管理当前用户的安全上下文信息。它主要用于在整个请求处理过程中存储和获取当前认证的用户信息

标签:令牌,浅谈,JWT,用户,认证,使用,服务器,springsecurity,请求
From: https://www.cnblogs.com/beyond-tester/p/17948327

相关文章

  • 使用 Python 进行简单的人脸识别
    介绍人脸识别技术已经成为当今世界许多领域的重要应用,从安全领域到社交媒体,无处不在。Python提供了许多强大的库和工具,使得实现人脸识别变得更加容易。本文将介绍如何使用Python中的一些流行库来进行简单的人脸识别。准备工作在开始之前,确保你已经安装了以下库:OpenCV:用于......
  • 在MFC中使用CArchive进行串行化数据
    使用CArchive进行数据串行化非常的方便。CArchive持有一个CFile对象,通过此对象进行读写,那么所有基于CFile的子类,都可以使用CArchive来进行串行化。示例:CFilefile(_T("1.txt"),CFile::modeReadWrite);CArchivear(&file,CArchive::load);此时CArchive对象就是处于读取的......
  • C#中Queue队列的基本使用示例
       在C#中,Queue是一个内置的FIFO(First-In-First-Out)集合,这意味着元素在队列中的顺序与它们被添加的顺序相同,当且仅当从队列中移除元素时,元素出队的顺序才是正确的。Queue在.NETFramework中是一个泛型集合类型,这意味着你可以存储任何类型的元素。它提供了许多方法来操作队列,......
  • 使用Apache Commons Chain实现命令模式
    第1章:引言大家好,我是小黑。今天咱们来聊聊一个挺有意思的话题:如何用ApacheCommonsChain实现命令模式。首先,得先搞明白什么是命令模式,对吧?命令模式,它其实是一种设计模式,主要用来把一个请求或者操作封装成一个对象。这样做的好处是什么呢?主要是让你的软件设计更加灵活,更容易扩展......
  • SpringBoot的Controller,Service,Repository层的使用
    找回熟悉的Controller,ServiceController哪儿去了?对于很多习惯了Spring开发的同学来讲,Controller,Service,DAO这些套路突然间都没了会有不适感。其实呢,这些东西还在,只不过对于较简单的情景下,这些都变成了系统背后帮你做的事情。这一小节我们就先来看看如何将Controller再召唤回......
  • 账单&红包记录找回好友工具使用教程
    工具下载地址下载地址:https://wwot.lanzouw.com/b038zqpyh 密码:b69k模拟器下载MuMu模拟器:https://mumu.163.com/逍遥安卓模拟器:https://www.xyaz.cn/雷电模拟器:https://www.ldmnq.com/前期准备安装好模拟器,再下载微信并登录(下图以MuMu模拟器为例,其他模拟器也基本一致)。......
  • 使用Ventoy制作Win to Go和Fedora to Go双系统
    这是一次简短的记录整体的思路实际上是通过虚拟机制作安装好系统的虚拟磁盘文件,然后加载到Ventoy中,从Ventoy启动Ventoy官方网站在实现的过程中,首先需要对存储介质(U盘等等,我是用的是固态硬盘盒)进行初始化并安装Ventoy随后使用虚拟机来安装系统,装在物理机的硬盘上就可以了,......
  • 使用Python+selenium实现第一个自动化测试脚本
    这篇文章主要介绍了使用Python+selenium实现第一个自动化测试脚本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧最近在学web自动化,记录一下学习过程。此处我选用python3.6+selenium3.0,均用最新版本,以适应......
  • 使用Power Automate获取Dataverse数据作为Excel附件发送邮件
    这是我的第506篇原创文章,写于2024年1月5日。之前我写过一篇文章 使用PowerAutomate获取CDS中数据并附加到邮件中发送,发送的是CSV,如果要发送Excel呢?今天我根据 CreateAnExcelFileAndAddRowsUsingPowerAutomate 的文章来做个发送Excel的例子。我创建一个Manuallytrigg......
  • 使用Docker-ompose快速构建Nacos服务
    在微服务架构中,服务的注册与发现扮演着至关重要的角色。Nacos(NamingandConfigurationService)是阿里巴巴开源的服务注册与发现组件,致力于支持动态配置管理和服务发现。最近,一位朋友表达了对搭建一套Nacos开发环境的兴趣。先前,我们曾发布了一篇有关在Linux上直接部署Nacos的文章,标......