【SpringSecurity】快速入门—通俗易懂

news2024/11/23 15:22:48

目录

1.导入依赖

2.继承WebSecurityConfigurerAdapter

3.实现UserDetailsService

4.记住我

5.用户注销

6.CSRF理解

7.注解功能

7.1@Secured

7.2@PreAuthorized 

7.3@PostAuthorized

7.4@PostFilter

7.5Z@PreFilter

8.原理解析

1.导入依赖

首先,在pom.xml文件中添加Spring Security依赖:

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

2.继承WebSecurityConfigurerAdapter

创建一个WebSecurityConfig类,继承WebSecurityConfigurerAdapter:

继承WebSecurityConfigurerAdapter是因为我们要重写里面的方法 定义一些安全配置 例如:注销

功能、访问控制、登录页面等。

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

}

protected void configure(HttpSecurity http)这个方法用于配置拦截保护的HTTP请求 配置HTTP安

全性 定义哪些URL应该受到保护 哪些用户可以访问哪些URL 以及保护的URL应该执行哪些安全措

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.formLogin()
			//.loginPage("/login.html")//指定登录页面(这里不会前端,所以不写页面了)
			//.loginProcessingUrl("/authentication/form")//登录访问路径(登录页面的form表单提交路径)
			//.failureUrl("/error.html")//用户名或密码错误访问的页面
			//.usernameParameter("username")
			//.passwordParameter("password")   //要认证的 用户名, 密码  的参数名,默认username, password
			.defaultSuccessUrl("/index/toIndex").permitAll()//defaultSuccessUrl:登录成功后,是否始终跳转到登录成功url,它默认为false。  permitAll()就是指不需要拦截
		.and().authorizeRequests()
			.antMatchers("/index/testRoleAndPermission").hasAnyRole("admin")//设置哪些路径需要什么权限
			.antMatchers("/index/anyOne","/index/anyTwo").permitAll()//设置哪些路径可以直接访问,不需要认证
			.anyRequest().authenticated();//其余任何请求都需要认证
		.and().csrf()
			.disable();//关闭csrf防护
	}

public void configure(AuthenticationManagerBuilder auth) 这个方法主要是配置 身份验证机制 就

是配置密码匹配器和用户从数据库查询用户的service

// 用于配置身份验证机制
        // AuthenticationManagerBuilder常用方法:(下面的方法我没有写参数,实际情况可能是有参的)
                // inMemoryAuthentication(): 这个方法允许您在内存中配置用户详细信息。您可以指定用户名、密码和用户角色。这对于快速测试和开发目的非常方便。
                // userDetailsService(): 这个方法接受一个UserDetailsService对象,用于加载用户的详细信息。UserDetailsService是一个接口,您需要实现它来根据用户名加载用户信息。
                // jdbcAuthentication(): 这个方法允许您使用JDBC来加载用户详细信息。您需要提供一个DataSource对象和相应的查询语句来检索用户名、密码和角色信息。
                // ldapAuthentication(): 这个方法用于配置LDAP(轻量级目录访问协议)身份验证。您需要提供LDAP服务器的连接信息和相应的查询语句。
                // authenticationProvider(): 这个方法允许您提供自定义的AuthenticationProvider实现,用于验证用户的身份。

		// userDetailsService(T userDetailsService):    根据传入的自定义UserDetailsService做身份验证。
		// 返回值:                                       会返回一个DaoAuthenticationConfigurer(该类继承AbstractDaoAuthenticationConfigurer抽象类)}
        // passwordEncoder(PasswordEncoder passwordEncoder): 来自于抽象类, 用于指定自定义密码匹配器,便于后续springsecutiry底层后续使用。
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
	}

public PasswordEncoder passwordEncoder() 这个是密码匹配器 SpringSecurity校验密码的时候

就要用到密码匹配器 对密码进行加密解密校验对比操作

// 必须要个这种密码匹配器,springsecurity要求的,必须对密码进行加密。
	@Bean
	public PasswordEncoder passwordEncoder(){
		return new BCryptPasswordEncoder();
	}

3.实现UserDetailsService

客户端输入用户名和密码 后端必须要从数据库查询出数据 进行校验 需要实现UserDetailsService

重写查询校验方法

/**
 * @author lihao
 * @version 1.0
 * @ClassName SecurityUserServiceImpl
 * @date 2023/5/25  9:43
 * @apiNote UserDetailsService:用于加载用户的详细信息,以供身份验证和授权使用。它提供了一个方法loadUserByUsername(String username)用于用户名获取用户的详细信息。
 *                              我们想更改springcurity的认证,我们就可以实现UserDetailsService,因为security底层就是用其做核心认证的。
 **/
@Service
public class SecurityUserServiceImpl extends ServiceImpl<SecurityUserMapper, SecurityUser> implements SecurityUserService, UserDetailsService {
	
	@Resource
	private SecurityUserMapper securityUserMapper;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		LambdaQueryWrapper<SecurityUser> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(SecurityUser::getUsername,username);
		SecurityUser user = securityUserMapper.selectOne(wrapper);
		if (user==null) {
			throw new UsernameNotFoundException("用户没找到");
		}
		
        // loadUserByUsername方法需要返回一个UserDetails(接口),常用实现类User。因此我们返回一个SpringSecurity提供的User对象。
        // 该User对象所需的参数中,密码必须加密(由springsecurity要求),因为我前面已经在SecurityConfig配置了加密器,所以这里就不需要对密码进行加密。
        // 否则需要加密:new BCryptPasswordEncoder().encode(user.getPassword())  ---- 可以这么写

		// 第三个参数,他需要一个权限集合,这里只做认证,所以随便搞一个角色集合,不影响认证,注意,这里第三个参数不能直接传null,必须给它一个集合。
		List<GrantedAuthority> adminAuthority = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
		return new User(user.getUsername(), user.getPassword(), adminAuthority); // 已在SecurityConfig配置了加密组件,所以不需要对这里的密码加密。
	}

4.记住我

客户端登录一次以后 下次访问不用登录 直接访问 

需要在configure(HttpSecurity http)配置

// 开启记住我功能
http.rememberMe()
 .tokenRepository(tokenRepository)
 .userDetailsService(usersService);

 .tokenRepository(tokenRepository):这是为"记住我"功能配置token存储库。token是用来存储

和验证用户会话信息的。这通常是一个在数据库或其他持久性存储中保存信息的对象。

.userDetailsService(usersService):这是为"记住我"功能配置用户详情服务。

UserDetailsService是Spring Security中的一个接口,它有一个方法loadUserByUsername,用于根

据用户名获取用户信息。usersService需要实现这个接口,并能够根据用户名找到用户的详细信

息。这对于"记住我"功能很重要,因为它需要知道用户的详细信息(例如他们的加密密码)以验证

他们的身份。

@Autowired
private DataSource dataSource;
@Bean
public PersistentTokenRepository persistentTokenRepository(){
 JdbcTokenRepositoryImpl jdbcTokenRepository = new 
JdbcTokenRepositoryImpl();
// 赋值数据源
jdbcTokenRepository.setDataSource(dataSource);
// 自动创建表,第一次执行会创建,以后要执行就要删除掉!
jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
 }
}

还可以设置有效期

5.用户注销

http.logout().logoutUrl("/logout").logoutSuccessUrl("/index").permitAll
();
  1. http.logout(): 这是调用Spring Security的HTTP安全性配置的logout方法,它配置了用户的注销功能。
  2. .logoutUrl("/logout"): 这告诉Spring Security,当用户点击注销时,应该将他们重定向到URL "/logout"。这通常是应用程序的一个特殊页面,它执行注销操作并终止用户的会话。
  3. .logoutSuccessUrl("/index"): 当注销操作成功后,用户将被重定向到这个URL。在这个例子中,用户将被重定向到应用程序的"/index"页面。
  4. .permitAll(): 这告诉Spring Security,所有用户都应该能够访问注销功能。换句话说,它不限制谁可以注销,所有用户都可以。

总的来说,这段代码的目的是配置Spring Security的注销功能,使得所有用户都可以注销,并且当

他们注销成功后,他们将被重定向到应用程序的"/index"页面。

6.CSRF理解

跨站请求伪造 (英语: Cross-site request forgery ),也被称为 one-click
attack 或者 session riding ,通常缩写为 CSRF 或者 XSRF , 是一种挟制用户在当前已
登录的 Web 应用程序上执行非本意的操作的攻击方法。跟 跨网站脚本 XSS )相比, XSS
利用的是用户对指定网站的信任, CSRF 利用的是网站对用户网页浏览器的信任。
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个
自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买
商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。
这利用了 web 中用户身份验证的一个漏洞: 简单的身份验证只能保证请求发自某个用户的
浏览器,却不能保证请求本身是用户自愿发出的
Spring Security 4.0 开始,默认情况下会启用 CSRF 保护,以防止 CSRF 攻击应用
程序, Spring Security CSRF 会针对 PATCH POST PUT DELETE 方法进行防护。
开启CSRF后,Spring Security会添加一个CSRF令牌到表单提交的请求中,以确保只有合法的请
求才能被处理。这样可以防止攻击者通过注入恶意代码或跨站请求伪造等方式来篡改服务器资源。

7.注解功能

使用注解功能前 要先开启注解功能 在启动类加上@EnableGlobalMethodSecurity()注解 注解里面

要使用什么注解 就在括号里填写 xxx注解=true 例如:

@EnableGlobalMethodService(securedEnabled = true) 使用@securedEnabled注解

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled=true)
public class DemosecurityApplication {
public static void main(String[] args) {
 SpringApplication.run(DemosecurityApplication.class, args);
 }
}

7.1@Secured

判断是否具有这个角色 字符串前缀需要添加ROLE_

// 测试注解:
@RequestMapping("testSecured")
@ResponseBody
@Secured({"ROLE_normal","ROLE_admin"})
public String helloUser() {
return "hello,user";
}

7.2@PreAuthorized 

先开启注解功能:
@EnableGlobalMethodSecurity (prePostEnabled = true )
@PreAuthorize:注解适合进入方法前的权限验证, @PreAuthorize 可以将登录用
户的 roles/permissions 参数传到方法中。
@RequestMapping("/preAuthorize")
@ResponseBody
//@PreAuthorize("hasRole('ROLE_管理员')")
@PreAuthorize("hasAnyAuthority('menu:system')")
public String preAuthorize(){
 System.out.println("preAuthorize");
return "preAuthorize";
}

7.3@PostAuthorized

先开启注解功能:
@EnableGlobalMethodSecurity (prePostEnabled = true )
@PostAuthorize 注解使用并不多,在方法执行后再进行权限验证,适合验证带有返回值
的权限 .
@RequestMapping("/testPostAuthorize")
@ResponseBody
@PostAuthorize("hasAnyAuthority('menu:system')")
public String preAuthorize(){
 System.out.println("test--PostAuthorize");
return "PostAuthorize";
}

7.4@PostFilter

@PostFilter :权限验证之后对数据进行过滤 留下用户名是 admin1 的数据
表达式中的 filterObject 引用的是方法返回值 List 中的某一个元素
@RequestMapping("getAll")
@PreAuthorize("hasRole('ROLE_管理员')")
@PostFilter("filterObject.username == 'admin1'")
@ResponseBody
public List<UserInfo> getAllUser(){
 ArrayList<UserInfo> list = new ArrayList<>();
 list.add(new UserInfo(1l,"admin1","6666"));
 list.add(new UserInfo(2l,"admin2","888"));
return list;
}

7.5Z@PreFilter

@PreFilter: 进入控制器之前对数据进行过滤
@RequestMapping("getTestPreFilter")
@PreAuthorize("hasRole('ROLE_管理员')")
@PreFilter(value = "filterObject.id%2==0")
@ResponseBody
public List<UserInfo> getTestPreFilter(@RequestBody List<UserInfo> 
list){
 list.forEach(t-> {
 System.out.println(t.getId()+"\t"+t.getUsername());
 });
return list;
}

8.原理解析

SpringSecurity本质:其实就是一个过滤器链,内部提供了各种功能的过滤器。springsecurity底层就是这些过滤器一层一层的执行帮我们实现的权限管理。

图中只展示了核心过滤器,其它的非核心过滤器并没有在图中展示。

UsernamePasswordAuthenticationFilter: 用于处理基于表单的登录请求,从表单中获取用户名和

密码。 默认情况下处理来自 /login 的请求。从表单中获取用户名和密码时,默认使用的表单 name

值为 username 和 password。 这两个值可以通过设置这个过滤器的usernameParameter 和

passwordParameter 两个参数的值进行修改。 其内部还有 登录成功 或 失败后 进行处理的

AuthenticationSuccessHandler 和 AuthenticationFailureHandler,这些都可以根据需求做相关改

变。

ExceptionTranslationFilter: 处理 AccessDeniedException 和 AuthenticationException 异常。 3.

FilterSecurityInterceptor: 是用于保护web资源的,使用 AccessDecisionManager 对当前用户进

行授权访问。

SpringSecurity认证流程:

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

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

相关文章

第五章 I/O管理 二、I/O控制器

目录 一、电子部件 1、I/O控制器 1.功能&#xff1a; &#xff08;1&#xff09;接受和识别CPU发出的命令&#xff1a; &#xff08;2&#xff09;向CPU报告设备的状态 &#xff08;3&#xff09;数据交换 &#xff08;4&#xff09;地址识别 2.组成 二、内存映像和寄…

磁盘调度算法之先来先服务(FCFS),最短寻找时间优先(SSTF),扫描算法(SCAN,电梯算法),LOOK调度算法

目录 1.一次磁盘读/写操作需要的时间1.寻找时间2.延迟时间3.传输时间4.影响读写操作的因素 2.磁盘调度算法1.先来先服务(FCFS)1.例题2.优缺点 2.最短寻找时间优先(SSTF)1.例题2.优缺点3.饥饿的原因 3.扫描算法(SCAN)1.例题2.优缺点 4.LOOK调度算法1.例题2.优点 5.循环扫描算法(…

81 分割回文串

分割回文串 题解1 回溯题解2 回溯dp利用dp相当于先判断哪段是回文(省掉了每次都需要调用的isValid)【预处理】 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使 每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字…

【idea】新建Maven文件都会默认在C盘下载的解决方法

Customize——>All settings 完成配置 同理&#xff0c;其他需要全局配置的设置步骤也是一样的。

第9天:字符编码

字符编码 字符串类型、文本文件的内容都是由字符组成的&#xff0c;但凡涉及到字符的存取&#xff0c;都需要考虑字符编码的问题。 存储原理&#xff1a; 1、软件运行前&#xff0c;软件的代码及其相关数据都是存放于硬盘中的 2、任何软件的启动都是将数据从硬盘中读入内存&…

JAVA-JVM 之Class字节码文件的组成 【上篇】

字节码 前言概述基本结构魔数头版本号常量池访问标志 主页传送门&#xff1a;&#x1f4c0; 传送 前言 java的特点是跨平台性&#xff0c;而跨平台的运行标准是Class字节码文件&#xff0c;Class字节码是提供平台无关性的基础模型&#xff0c;使我们无须考虑如何兼容异构系统&…

车载电子电器架构 —— 基于AP定义车载HPC

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

提升演讲与口才的三种方法

演讲和口才是在现代社会中非常重要的技能。无论是在职场中进行演讲&#xff0c;还是在日常生活中与他人进行交流&#xff0c;具备良好的演讲和口才能力都能给人带来诸多优势。然而&#xff0c;要提升自己的演讲和口才能力并不是一件容易的事情。在本文中&#xff0c;我将介绍三…

【机器学习】决策树与分类案例分析

决策树与分类案例分析 文章目录 决策树与分类案例分析1. 认识决策树2. 分类3. 决策树的划分依据4. 决策树API5. 案例&#xff1a;鸢尾花分类6. 决策树可视化7. 总结 1. 认识决策树 决策树思想的来源非常朴素&#xff0c;程序设计中的条件分支结构就是if-else结构&#xff0c;最…

pre-existing shared memory block

发生原因: 1.服务器cpu、内存进行扩容 2.非正常关闭,导致任在占用共享内存段 解决方案: 根据shmid进行关闭 ipcs -mipcrm -m xxx

进程替换..

1、单进程版 – 最简单的先看看程序替换 现象就是 1、我们用自己的进程封装了内置指令ls,并且代码中execl 后 printf 的after并没有打印出来。 2、谈进程替换的原理 单进程替换基本原理 上面例子中execl的做法非常简单粗暴&#xff0c;要调用ls&#xff0c;那么就把mycom…

使用Python,mediapipe构建手部姿势探测器

使用Python&#xff0c;mediapipe构建手部姿势探测器 1. 效果图2. 手部标志3. 源码参考 这篇博客将介绍手部标志是什么&#xff0c;以及如何使用Python&#xff0c;mediapipe构建手部姿势探测器&#xff0c; Mediapipe是一个跨平台的库&#xff0c;由谷歌开发&#xff0c;为计…

【pandas技巧】group by+agg+transform函数

目录 1. group by单个字段单个聚合 2. group by单个字段多个聚合 3. group by多个字段单个聚合 4. group by多个字段多个聚合 5. transform函数 studentsgradesexscoremoney0小狗小学部female958441小猫小学部male938362小鸭初中部male838543小兔小学部female909314小花小…

KubeSphere 社区双周报 | KubeKey 支持 Web UI | 2023.10.13-10.26

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.10.13-2023.…

No module named ‘skimage.viewer‘解决方法

问题 在使用https://github.com/DinoMan/face-processor工具时出现的问题 解决方法 scikit-image0.20官网中提到已经移除了skimage.viewer 可以安装0.18版本的&#xff1a; python -m pip install -U pip python -m pip install -U scikit-image0.18

【蓝桥每日一题]-前缀和与差分(保姆级教程 篇3)#涂国旗 #重新排序

目录 题目&#xff1a;涂国旗 思路&#xff1a; 题目&#xff1a;重新排序 思路&#xff1a; 题目&#xff1a;涂国旗 思路&#xff1a; 乍一看好像没啥思路&#xff0c;但是我们需要涂最少的格子&#xff0c;所以要都尝试一下才行&#xff0c;也就是从上面开始白至少一行&am…

SpringBoot 公司推广系统 公司广告系统

SpringBoot 公司推广系统 公司广告系统 系统功能 首页功能: 广告展示 方案列表 站内搜索 资讯 查看详细咨询 登录注册 收藏 咨询方案 在线客服实时聊天 后台管理功能: 系统管理分为: 用户管理 角色管理 客户管理 首页轮播管理 公告管理 方案管理: 方案管理 资讯管理: 类型管…

【OJ for Divide and Conquer】OJ题解

文章目录 A - Ultra-QuickSortB - Hanoi Tower Troubles Again! [找规律递归]C - Fibonacci Again[找规律]E - [Fire Net](https://programmerall.com/article/7276104269/)[DFS 搜索 ⭐⭐]F - Gridland[找规律]G - Maximum Subarray Sum[动态规划/分治..经典⭐]I - Quoit Desi…

在线运行C++的网站(欢迎补充)

1、https://cpp.sh/ 谷歌打开&#xff0c;好用 2、https://godbolt.org/ 会显示汇编

Beyond Compare4 30天试用到期的解决办法

相信很多小伙伴都有在使用Beyond Compare 4软件&#xff0c;如果我们没有激活该软件&#xff0c;就只有30天的评估使用期&#xff0c;那么过了这30天后我们怎么继续使用呢&#xff1f;下面小编就来为大家介绍方法。 打开Beyond Compare4&#xff0c;提示已经超出30天试用期限制…