项目中spring security与jwt.腾讯面试分享

写这篇文章是为了记录我面试pcg时平时没有留意或者钻研的地方。

面试是根据项目问的问题:

为什么采用jwt存储token?

        我的项目是微服务项目,里面部署了资源服务和认证服务,这里选择jwt作为token一方面是可以存储用户的信息,可以将用户身份信息存储在令牌中,用户认证通过后认证服务颁发令牌给用户,用户将令牌存储在客户端,去访问应用服务时携带令牌去访问,服务端从jwt解析出用户信息。也就是所说的无状态认证。如果是session认证的话存储在服务端会加大服务端的压力,不适合运用于分布式系统。

总结来说就是:灵活性,一致性,故障发生的可用性,以及多平台维护的代价。

        另一个目的也就是去实行资源的自认证,每次经过网关的时候,就判断令牌的有效性。以此来决定是否可以访问该资源。

jwt存储信息都存储在哪里,关键信息存储在里面么?

jwt的组成部分一般为三部分,头部,负载,和签名部分。我存储的信息一般放置于负载部分,当然,肯定是不建议将密码等私密信息存储在里面的。

spring security是如何和jwt进行结合的呢?

换句话说,如何设置springsecurity的令牌?

        这里我之前都是知道怎么去运用,并没有去看过源码,只知道这么配置一下就好了。但项目被拷打了,问了我意想不到的地方,但还是要好好去琢磨琢磨。

首先我们看令牌的配置在哪里

AuthorizationServerConfigurerAdapter这个类
ClientDetailsServiceConfigurer客户端详情的配置
AuthorizationServerSecurityConfigurer安全配置,谁能允许通过

说白了这三个配置都是需要你去实现的。但是我们这里只讲令牌。

这个bean是我们自己配置的,定义了bean并指定了名字。

配置一个TokenConfig

定义令牌服务:

可以看到这两个bean的名字是一样的。refreshToken解决的其实是令牌的续期问题。当jwt令牌快过期时使用刷新令牌可以再次生成jwt令牌。

jwt的加密方式是什么?

可以知道,jwt的整体可以用HMAC算法或使用RSA的公钥/私钥对来签名。我们的整理就是

  HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    secret)

这样的结构。使用base64编码对header和payload两个部分进行编码,再和secret一起加密。

base64:在参数传输的过程中经常遇到的一种情况:使用全英文的没问题,但一旦涉及到中文就会出现乱码情况。与此类似,网络上传输的字符并不全是可打印的字符,比如二进制文件、图片等。Base64的出现就是为了解决此问题,它是基于64个可打印的字符来表示二进制的数据的一种方法。 但是原理我个人认为看一遍就好了,不用去死记硬背。

数据库里的密码是明文存储的吗?前后端密码验证时如何比对的?

这个是我自己思考的问题,也是我重新看代码的时候看的。

说到这里,我们不妨从头开始顺一下spring security自带的流程。

我们输入的密码一般是变成表单提交,那么它会被封装到AUthentication里。

我们可以看到这里的调用关系AuthenticationManager调用DaoAuthenticationProvider,而DaoAuthenticationProvider里的UserDetailsService里又会调用loadUserByUsername来获取用户的信息,并将获取到的用户信息以springsecurity里的Userdetail方式返回。注意这里通过PasswordEncoder的BCryptPasswordEncoder方式,这个是暗文存储。我觉得可以记一下这个加密方式,因为被问了,我就没记住这个,因为我觉得这个不是重点但还真问了。

BCryptPasswordEncoder

配置这个来决定security框架自身的密码比对。密码的形式,这个是自带的!!

当然也可以手动的自行配置,不用框架自带的 UserDetailsService也就是可以重写loadUserByUsername方法和比对方式。

这里就会发现,encode里竟然发现了salt字样,没错,BCryptPasswordEncoder里面自带加盐操作,如果你不指定,那么他会按照自己的配置的一些值来给你加盐。

获取盐代码:

加密算法:

通过输入密码和根据密码特点获得的盐来进行加密

random.nextBytes(rnd);

因为每次的 salt 不同,因此每次的 hash 也不同。这样就可以使得相同的 明文 生成不同的 密文

那么如果这个数据库中的密码,我们是通过BCryptPasswordEncoder加密的存储在数据库当然中的。我们应该如何进行比较用户输入的是否正确呢?因为用户输入的密码也不是暗文的啊。

那么怎么知道用户输入的密码和数据库中的密码是否一致呢?

这里还是要看BCryptPasswordEncoder的源码

继续跟踪hashpw这个方法,我们会发现和加密时候的方法hashpw是一样的。

我们会发现,这个方法会将自己定义的盐取出来,并且base64解码,最后和我们的密码加密一下,然后和之前的数据库的暗文进行对比。

是否了解加盐,如何加盐,加盐的意义是什么?

个人理解我觉得可以和jwt的secret部分做类比。都是通过添加随机的一部分。安全的提高就是:随机数+混入形式。

        密码加盐里包含随机值和加密方式。随机值是随机产生的,并且以随机的方式混在原始密码里面,然后按照加密方式生成一串字符串保存在服务器。换言之,这个是单向的,电脑也不知道客户的原始密码,即使知道加密方式,反向推出的加密前的字符串也是真正密码与随机值混合后的结果,从而无法解析用户的真正密码。那么是如何验证密码的呢?当你再次输入密码,会以相同的加盐方式生成字符串,如果和之前的一致,则通过。而其它用户无法获得这种加密方式:即生成哪些随机数,以什么方式混入进去,自然就很安全。

如何生成随机字符串?

可以使用org.apache.commons.lang包下有一个RandomStringUtils类,其中有一个randomAlphanumeric(int length)函数,可以随机生成一个长度为length的字符串。 

RandomStringUtils.randomAlphanumeric(10);

加盐的意义用gpt解释的来看吧。 

前后端密码验证的时候是如何比对的?

jwt的密钥存储在哪里?

这里附属上gpt

jwt的负载部分内容是从哪获得的?

这个也是自己的思考,其实我也好奇为什么这么设置就可以改变jwt里负载的内容。

这个还得跟踪spring security里代码

点击一下

JwtAccessTokenConverter 

我们可一看到这个里面实现了两个类,我们可以通过tokenenhance里的enhance编写自己的enhance方法来增强扩展这个token信息。当然这里要看的是AccessTokenConverter

一直好奇这里的负载信息哪来的,这就有个信息提取方法

终于看到了这个username

这里其实也就是我们在返回userdetail信息里的username

而extractAutentication里的其他信息我画红色的也来自于我们的客户端配置

  public void configure(ClientDetailsServiceConfigurer clients)
          throws Exception {
        clients.inMemory()
                .withClient()// client_id
                .secret()//客户端密钥
                .resourceIds()//资源列表
                .authorizedGrantTypes()// 该client允许的授权类型
                .scopes()// 允许的授权范围
                .autoApprove()//false跳转到授权页面
                //客户端接收授权码的重定向地址
                .redirectUris()
   ;
  }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/434924.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv7独家原创改进:特征融合涨点篇 | 广义高效层聚合网络(GELAN) | YOLOv9

💡💡💡本文独家改进:即结合用梯度路径规划(CSPNet)和(ELAN)设计了一种广义的高效层聚合网络(GELAN),高效结合YOLOv7,实现涨点。 将GELAN添加在backbone和head处,提供多个yaml改进方法 💡💡💡在多个私有数据集和公开数据集VisDrone2019、PASCAL VOC实现…

FPGA开发之libero元件实例化详细步骤

FPGA开发之libero模块实例化详细步骤 第一步,假设已经建立了两个文件,现在需要将这两个文件连接在一起,如下图所示: 第二步,建立一个SD顶层文件,操作如下: 得到结果如下: 点击OK得…

continue、break 和 return 的区别是什么?

continue、break和return同样是用于控制程序流程的关键字,它们有不同的作用和用法。 continue: 在Java中,continue语句同样通常用于循环结构(如for循环、while循环)。当程序执行到continue时,会立刻跳过当前循环中剩…

第三百八十六回

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了Snackbar Widget相关的内容,本章回中将介绍TimePickerDialog Widget.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在这里说的TimePickerDialog是一种弹出窗口,只不过窗口的内容固定显示…

K8s集群调度,亲和性,污点,容忍,排障

目录 1.调度约束 调度过程 指定调度节点 查看详细事件 获取标签帮助 修改成 nodeSelector 调度方式 2.亲和性 节点亲和性 Pod 亲和性 键值运算关系 硬策略 软策略 Pod亲和性与反亲和性 创建一个标签为 appmyapp01 的 Pod 使用 Pod 亲和性调度,创建多…

Win11桌面出现的这个图标“了解此图片”怎么关闭?

🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉 在csdn获奖荣誉: 🏆csdn城市之星2名 ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ …

【OpenGL的着色器03】内置变量和函数(gl_Position等)

目录 一、说明 二、着色器的变量 2.1 着色器变量 2.2 着色器内置变量 三、最常见内置变量使用范例 3.1 常见着色器变量 3.2 示例1: gl_PointSize 3.3 示例2:gl_Position 3.4 gl_FragColor 3.5 渲染点片元坐标gl_PointCoord 3.6 gl_PointCoo…

LVS四层负载均衡集群

简介 LVS(Linux Virtual Server)即Linux虚拟服务器,是由章文嵩博士主导的开源负载均衡项目,目前LVS已经被集成到Linux内核模块中。该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案,终端互联网用户从外部访…

liunx操作系统 进程的基本概念

进程的基本概念 计算机结构体系冯诺依曼 操作系统的管理进程进程的特性标识符系统的调用 创建新的进程 进程的状态进程队列进程的状态在liunx查看进程状态、 进程优先级 计算机结构体系 冯诺依曼 在没有存储器之前,所有的信息都是直接进入CPU,这样效率很…

测试遍历1e5,1e8数组耗时

1e8大概0.38秒,即380ms 1e5耗时1ms左右: 代码使用方式来自:clock - C Reference (cplusplus.com)

第十三届蓝桥杯嵌入式省赛程序设计详细题解

第十三届蓝桥杯嵌入式省赛题目相对于第十二届较为简单,没有那么多串口的数据处理以及判断! 第十三届省赛主要是制作一个可由串口设置密码的密码锁。本实验中,我们将用到LED模块、按键模块、串口模块、定时器的PWM模块以及官方会提供源码的LC…

STM32CubeIDE基础学习-软件安装,环境搭建

STM32CubeIDE基础学习-软件介绍及环境搭建步骤 文章目录 STM32CubeIDE基础学习-软件介绍及环境搭建步骤前言第1章 STM32CubeIDE 介绍1.1 软件描述1.2 软件支持的功能及特点 第2章 STM32CubeIDE 软件安装2.1 STM32CubeIDE 软件获取方法2.2 STM32CubeIDE 软件安装步骤2.2.1 错误安…

YOLOv9独家原创改进|加入RT-DETR中的HGBlock!

专栏介绍:YOLOv9改进系列 | 包含深度学习最新创新,主力高效涨点!!! 一、改进点介绍 HGBlock是RT-DETR中使用的特征提取模块。 二、HGBlock模块详解 2.1 模块简介 HGBlock的主要思想: 一个并联的卷积模块与…

STM32(19)I2C模块 主机发数据

发送数据: 等待空闲: 发送起始位: 发送地址: 发送数据:

TypeScript学习笔记(上):TypeScript的介绍、安装及常用类型

我对TypeScript的理解就是,TypeScript是增加了类型校验的JavaScript,能够把运行期错误提升至编译期 TypeScript是什么? TypeScript(简称:TS)是 JavaScript 的超集(JS 有的 TS 都有&#xff09…

【牛客】VL65 状态机与时钟分频

描述 题目描述: 使用状态机实现时钟分频,要求对时钟进行四分频,占空比为0.25 信号示意图: clk为时钟 rst为低电平复位 clk_out 信号输出 Ps 本题题解是按照1000的状态转移进行的,不按照此状态进行,编译器…

实现一个网页版的简易猜数字游戏

实现一个网页版的简易猜数字游戏 效果 代码截图 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><t…

3.6作业

作业要求&#xff1a;数据库操作的增、删、改 程序代码&#xff1a; #include<myhead.h> int main(int argc, const char *argv[]) {//定义数据库句柄指针sqlite3 * ppDb NULL;//打开数据库&#xff0c;如果数据库不存在&#xff0c;则创建数据库//将数据库句柄由参数…

【软件工程】软件工程定义、软件危机以及软件生命周期

&#x1f338;博主主页&#xff1a;釉色清风&#x1f338;文章专栏&#xff1a;软件工程&#x1f338; 今日语录&#xff1a;What matters isn’t how others think of your ambitions but how fervently you cling to them. 软件工程系列&#xff0c;主要根据老师上课所讲提及…

数字化转型导师坚鹏:金融科技咨询方法论

金融科技咨询方法论 ——方法、做法、演法、心法 课程背景&#xff1a; 数字化转型背景下&#xff0c;很多机构存在以下问题&#xff1a; 不知道先进的金融科技咨询方法论&#xff1f; 不知道如何运作金融科技咨询项目&#xff1f; 不知道如何汇报咨询项目关键成果&…