SpringSecurity学习总结(三更草堂)

news2024/11/28 12:33:17

SpringSecurity安全框架的核心功能认证授权

        认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户。

        授权:经过认证后判断当前用户是否具有进行某个操作权限。

        一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多,因为相比与SpringSecurity,Shiro的上手更加的简单。

二、入门案例:

2.1、创建Springboot项目:勾选SpringSecurity依赖

在SpringBoot项目中使用SpringSecurity我们只需要引入依赖即可实现入门案例:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        引入依赖后,启动Springboot应用,尝试去访问hello接口就会自动跳转到一个SpringSecurity的默认登陆页面,默认用户名是user, 密码会输出在控制台,必须登陆之后才能对接口进行访问:

@RestController
public class SecurityController {
    @RequestMapping("/hello")
    public String helloController(){
        return "欢迎使用SpringSecurity";
    }
}
2.2、启动应用,访问接口:

        当我们访问:http://localhost:8080/hello 时,会自动跳转到默认的登陆页面:

2.3、入门案例中 SpringSecurity 的流程:

        SpringSecurity 的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器 ,这里我们可以看看入门案例中的过滤器:图中只展示了核心过滤器,其它的非核心过滤器没有展示。

        UsernamePasswordAuthenticationFilter:负责处理我们在登陆页面填写了用户名、密码后的登陆请求。入门案例的认证工作主要有它负责。

    ExceptionTranslationFilter: 处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException 。

        FilterSecurityInterceptor: 负责权限校验的过滤器

 我们可以通过Debug查看当前系统中SpringSecurity过滤器链中有哪些过滤器及它们的顺序:

入门案例中的SpringSecurity过滤器链里有15个过滤器:

        {DefaultLoginPageGeneratingFilter@6504} 这个Filter功能是用来显示默认的登录页,如果说你不想要默认登录页,到时候不要加他就可以了,

        {DefaultLogoutPageGerneratingFilter@6505}这个Filter功能是用来显示默认的注销页面

2.4、入门认证流程详解:

概念速查:

Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。它用来表示的是当前访问系统的用户,可以在里面封装一些用户的相关信息,比如说用户名、密码,然后包括用户的一些权限都可以。但是在这个情况下,你看他只提交了用户名、密码,那他装的对象里面也只有用户名和密码信息

AuthenticationManager接口:定义了认证Authentication的方法

UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。会把这些用户信息权限信息又封装成一个UserDetails对象,这也是一个接口,它的核心提供了用户信息,我们可以把查到的用户的一些信息封装到这个接口的一个对象里面去。

UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。
 

2.5、入门案例的缺点分析:

        1、在我们前后端分离的项目中,我们不需要springsecurity提供的默认登录页,给它删除,我们需要自定义登录接口;

        2、入门案例里面用户名和密码,用户名默认为user,密码是它随机生成的,这肯定是不行的。我们应该是让他去数据库里面去进行用户名、密码的校验;

        3、入门案例它是基于session去实现这种登录。前后端不分离的时候可以用session,前后端分离,就不能使用session了,当用户的用户名、密码校验成功后,我们应该①:以用户id生成jwt,作为token响应给前端;② 同时以用户id作为key,用户信息作为value,存入Redis中;(实际项目中用不用 "用户id" 作为jwt、作为key看具体的项目需求)

        4、当我们校验用户有没有权限去访问当前他所请求的这个资源时,我们应该去获取请求头中的token进行解析,去判断有没有权限访问当前资源 

三、自定义登录的认证:

  实际前后端分离的项目中,去进行认证,核心其实依赖的就是token,你可以理解成它是一个加密之后的一个字符串,我通过前端是否携带这个token,去判断你是不是我系统的用户、你究竟是哪一个用户,这是它的一个核心思路

3.1、自定义的登录认证需要实现两大功能:登录、校验

登录

​         ①自定义登录接口:

                 把用户输入的用户名和密码封装成Authentication对象

​                 调用ProviderManager的authenticate()方法进行认证

                 如果认证没通过给用户对应的提示信息

                 如果认证通过则生成jwt作为token返回给前端,并且把用户信息存入redis中

​         ②自定义UserDetailsService接口的实现类

​                 在这个实现类中去查询数据库

校验:

​         ①定义Jwt认证过滤器

​                 获取token

​                 解析token获取其中的userid

​                 从redis中获取用户信息

​                 存入SecurityContextHolder

3.2、"自定义登录接口"的具体思路、流程:

        ①、默认情况下定义的接口,都会被我们SpringSecurity保护,要求必须认证后,才能够访问,而这个登录接口,必须设置为让SpringSecurity放行,让用户访问登录接口的时候不需要登录也能够访问,否则会相互矛盾

        ②、我们自定义一个登录接口,其实就是定义一个Controller去接受用户输入的用户名和密码,然后在Controller中去调用Service,在Service当中进行具体的业务操作,这个登录接口的请求方式为Post,所以要使用@PostMapping

         ③、具体的业务操作包括:

用户名和密码封装成Authentication对象

调用AuthenticationManager的authenticate()方法进行认证

密码加密存储PassWordEncoder

        实际项目中我们不会把密码明文存储在数据库中。
        默认使用的PasswordEncoder要求数据库中的密码格式为: {id}password。它会根据id去判断密码的加密方式,如果没加密,就是{noop}password。但是我们一般不会采用这种方式。所以需要替换PasswordEncoder。 
        我们一般使用SpringSecurity为我们提供的BCryptPasswordEncoder,我们只需要使用把BCryptPasswordEncoder对象注入Spring容器中,SpringSecurity就会使用BCryptPasswordEncoder来进行密码校验。

BCryptPasswordEncoder简介:

1 、BCryptPasswordEncoder是采用SHA-256 +随机盐+密钥对明文密码进行加密。SHA系列是Hash算法,不是加密算法,使用加密算法意味着可以解密(这个与编码/解码一样),但是采用Hash处理,其过程是不可逆的。BCrypt 是一种强哈希算法,它能很好地防止被暴力破解。

2、加密(encode):注册用户时,采用SHA-256+随机盐+密钥把用户输入的密码进行hash处理,得到密码的hash值,然后将其存入数据库中。因为每次的随机盐不同,导致对同一明文密码加密后得到的加密结果都不一样。密文中本身包含了很多信息,包括 salt 和 使用 salt 加密后的 hash。

3、密码匹配(matches):用户登录时,密码匹配阶段并没有进行密码解密(因为密码经过Hash处理,是不可逆的),而是使用相同的算法把用户输入的密码进行hash处理,得到密码的hash值,然后将其与从数据库中查询到的密码hash值进行比较。如果两者相同,说明用户输入的密码正确。

4、这正是为什么处理密码时要用hash算法,而不用加密算法。因为这样处理即使数据库泄漏,黑客也很难破解密码!


 BCryptPasswordEncoder举例:

        我们可以定义一个SpringSecurity的配置类,SpringSecurity要求这个配置类要继承WebSecurityConfigurerAdapter:

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

 

@SpringBootTest
class Boot3SpringsecurityApplicationTests {
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Test
    public void testBCryptPasswordEncoder(){
       // BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        //传入密码的明文,它就会帮你进行加密,然后返回加密之后的字符串
        String encode1 = passwordEncoder.encode("123456");
        String encode2 = passwordEncoder.encode("123456");
        System.out.println("encode1: "+encode1);
        System.out.println("encode2: "+encode2);
        //第一个参数传入的是登录时候用户输入的密码,明文,然后和你数据库当中查到的加密后的密文比较:
        boolean flag1 = passwordEncoder.matches("123456",encode1);
        boolean flag2 = passwordEncoder.matches("123456",encode2);
        System.out.println("flag1为"+flag1);
        System.out.println("flag2为"+flag2);
    }

}
LoginUser implements UserDetails:

到时候框架里面会调用loginUser的getPassword()方法来获取当前用户的密码之类的
 

                                

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginUser implements UserDetails {
    private User user;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUserName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }
}

自定义登录接口:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无尘卷轴布:保障洁净环境的关键利器

在现代科技高度发达的今天&#xff0c;许多行业对于环境洁净度的要求越来越严格&#xff0c;比如半导体制造、医疗器械生产等。而在这些领域中&#xff0c;无尘卷轴布成为了一项至关重要的辅助工具&#xff0c;其独特的设计和材质特性&#xff0c;为保障洁净环境做出了突出贡献…

如何备份 Outline 导出的 Markdown 文件

前面&#xff0c;我撰写了两篇文章&#xff0c;介绍了&#xff1a; 《如何在本地环境安装 Outline》《使用 Outline 搭建企业、个人知识库面临的问题》 今天&#xff0c;我们继续这个话题。使用 Outline 搭建知识库&#xff0c;如何备份自己知识库内的资料。 Outline 底层使用…

【教学类-09-03】20240401细线迷宫图02(A4横版一页-2份竖版)

作品展示&#xff1a; 背景需求&#xff1a; 【教学类-09-02】20240331细线迷宫图01&#xff08;A4横版一页1份横版&#xff09;-CSDN博客文章浏览阅读779次&#xff0c;点赞28次&#xff0c;收藏6次。【教学类-09-02】20240331细线迷宫图01&#xff08;A4横版一页1份横版&…

Sentinel入门Controller自动定义为资源

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流…

【opencv】教程代码 —ShapeDescriptors

检测和显示图像的轮廓 在图像中搜索并显示轮廓边缘多边形、轮廓矩形和包围圆 获取包含检测到的轮廓的椭圆和旋转的矩形 图像轮廓检测和轮廓凸包 计算图像中的轮廓的矩&#xff08;包括面积、重心等&#xff09;并进行显示 创建和绘制一个多边形图像然后计算并显示图像上每个点到…

使用Vue3组件的计算属性

计算属性在Vue.js的computed选项中定义&#xff0c;它可以在模板上进行双向数据绑定以展示出结果或者进行其他处理。 通常用户会在模板中定义表达式&#xff0c;非常便利&#xff0c;Vue.js的设计初衷也是用于简单运算。但是在模板中放入太多的逻辑&#xff0c;会让模板变得臃…

项目管理中,项目延期的这些原因,你经历过几个

在项目管理过程中&#xff0c;项目延期是一种常见的现象&#xff0c;深入了解项目延期的原因&#xff0c;并制定相应的应对策略&#xff0c;对于提高项目管理的效率和成功率至关重要。 项目延期的主要原因&#xff1a; 1、估计不足&#xff1a;在项目初期&#xff0c;对项目…

iOS网络抓包工具大曝光:深入了解常用工具的工作原理与应用场景

摘要 本文将深入探讨iOS平台上常用的网络抓包工具&#xff0c;包括Charles、克魔助手、Thor和Http Catcher&#xff0c;以及通过SSH连接进行抓包的方法。此外&#xff0c;还介绍了克魔开发助手作为iOS应用开发的辅助工具&#xff0c;提供的全方面性能监控和调试功能。 在iOS应…

DC-DC芯片D1509, 适用于工控主板、TV板卡、安卓主板、车载功放电源等产品方案应用。

一、应用领域 适用于工控主板、TV板卡、安卓主板、车载功放电源等产品方案应用。 二、功能介绍 D1509是芯谷科技推出的一款输入耐压40V、输出电压1.23-37V可调、输出电流最大2.0A的高效率、高精度DC-DC芯片&#xff0c;其输出电压有固定3.3V、5.0V和12.0V的版本&#xff0c;…

Pygame基础8-碰撞

Collisions 在Pygame中&#xff0c;我们使用矩形来移动物体&#xff0c;并且用矩形检测碰撞。 colliderect检测两个矩形是否碰撞&#xff0c;但是没法确定碰撞的方向。 Rect1.colliderect(Rect2) # collision -> return Ture # else -> return Falsecollidepoint可以…

中视频双去重,一键多平台,可达日入2000+

【核心】将不可复制的飞书文档&#xff0c;用大模型二创&#xff0c;进而生成思维导图&#xff08;视频&#xff09;&#xff0c;以下全过程使用工具半自动完成。 【飞书】https://puojikpj98.feishu.cn/docx/KUNad8Y0UoFHEexMyAfc7sA1nQf 【文案】 中视频双去重与多平台发布项…

“315晚会”中的“网络水军”是什么?

水军一词&#xff0c;源自网络用语&#xff0c;通常指的是一群在网络上被雇佣来进行特定活动的人群。他们的主要任务通常是在各种社交媒体平台、论坛或者评论区发表大量的帖子、评论或者回复&#xff0c;以此来达到某种特定的目的。这些目的可能包括提升某个产品、服务或者个人…

Python(django)之单一接口展示功能前端开发

1、代码 建立apis_manage.html 代码如下&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>测试平台</title> </head> <body role"document"> <nav c…

OpenTofu路在何方:定量分析Terraform issue数据,洞察用户需求|OpenTofu Day 闪电演讲

数澈软件 Seal 首席架构师李平辉提交的演讲议题“Alias TerraformTofu. Job’s Done, Now What?”入选 KubeCon EU 同场活动 OpenTofu Day&#xff0c;本文为演讲实录。 大家好&#xff0c;我是 Lawrence&#xff0c;是 Seal 的首席架构师。今天将由我为大家带来 Lightening T…

基于springboot实现房产销售系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现房产销售系统演示 摘要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于房产销售系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了房产销售系统…

B树、B+树、哈夫曼树

目录 1. B树2. B树3. 哈夫曼树 1. B树 特点&#xff1a;一个节点当中可以有多个值&#xff0c;节点内部key 值是有序的&#xff0c;节点内部存储的是key-value类型的数据 磁盘中文件存储用B树。 4阶B树一个节点最多三个key值 5阶B树一个节点最多四个key值 B树有很多的分支&…

数字化转型如何帮助企业降低经营成本?

数字化转型通过多种方式帮助企业降低经营成本&#xff0c;提高效率和竞争力。以下是一些关键的转型策略和实践&#xff1a; 1.自动化流程&#xff1a;利用自动化工具和软件&#xff0c;如机器人流程自动化&#xff08;RPA&#xff09;和人工智能&#xff08;AI&#xff09;&am…

优化页面加载时间:改善用户体验的关键

✨✨ 祝屏幕前的您天天开心&#xff0c;每天都有好运相伴。我们一起加油&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 一、为什么页面加载时间重要&#xff1f; 二、如何减少页面加载时间&#xff1f; …

MySQL count函数的使用

count&#xff08;&#xff09;函数在使用时参数好像不能设置为表达式&#xff0c;只能设置成指定字段或* 比如在查询性别为男的成员数目时不能写&#xff1a; select count(gendermale) from user_profile ; 否则直接得到6&#xff0c;也就是等价于select count(gender) fro…

SpringBoot常见注解有哪些

Spring Boot的核心注解是SpringBootApplication , 他由几个注解组成 : ● SpringBootConfiguration&#xff1a; 组合了- Configuration注解&#xff0c;实现配置文件的功能&#xff1b; ● EnableAutoConfiguration&#xff1a;打开自动配置的功能&#xff0c;也可以关闭某个自…