【Spring Security】 入门实战
文章目录
- 一、基本概念
- 二、Spring Security第一个程序
- 三、Spring Security没有生效
- 四、修改默认账号密码(appliction.yml)
- 五、修改默认账号密码(配置类)
- 六、Spring Security的三个configure方法
- 七、Spring Security的三种身份的验证
一、基本概念
单点登录
- 什么叫做单点登录呢。就是在一个多应用系统中,只要在其中一个系统上登录之后,不需要在其它系统上登录也可以访问其内容。
- 举个例子,京东那么复杂的系统肯定不会是单体结构,必然是微服务架构,比如订单功能是一个系统,交易是一个系统…那么我在下订单的时候登录了,付钱难道还需要再登录一次吗,如果是这样,用户体验也太差了吧。
- 实现的流程就是我在下单的时候系统发现我没登录就让我登录,登录完了之后系统返回给我一个Token,就类似于身份证的东西;然后我想去付钱的时候就把Token再传到交易系统中,然后交易系统验证一下Token就知道是谁了,就不需要再让我登录一次。
JWT(JSON Web Token)
Token的生成与解密

RSA(非对称加密算法)
从上面的例子中可以看出,JWT在加密解密的时候都用到了同一个密钥 “ robod666 ”,这将会带来一个弊端,如果被黑客知道了密钥的内容,那么他就可以去伪造Token了。所以为了安全,我们可以使用非对称加密算法RSA。

二、Spring Security第一个程序
Spring Security导入依赖就能生效了。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>
查看Controller层结果
@RestController
public class UserController {@AutowiredUserMapper userMapper;@RequestMapping("/user/select/{id}")public User list(@PathVariable("id") int id){return userMapper.queryUserById(id);}
}
启动项目,默认账号是user,密码在输出控制信息中

在浏览器中访问localhost:8080/user/selet/2,会自动跳转到localhost:8080/login

输入账号密码,跳转到我们原来请求的内容localhost:8080/user/selet/2

三、Spring Security没有生效
Spring Security在导入依赖之后就能生效,并且会使用一些默认配置。但是有时候导入依赖之后访问页面,也没有跳转到指定验证页面,这就是Spring Security没有生效。
这是因为,你在pom.xml中导入了依赖包,等于告诉maven要导入Spring Security依赖,但是不等于已经导入了Spring Securtiy,因为maven可能还没来得及导入,你就已经启动项目了。我们可以通过查看External Libraries这里,看看Spring Security是否已经导入成功。

四、修改默认账号密码(appliction.yml)
在application.yml配置文件中修改默认账号密码

启动项目,在浏览器中访问localhost:8080/user/selet/2,会自动跳转到localhost:8080/login,账号是nicky,密码在123

输入账号密码,跳转到我们原来请求的内容localhost:8080/user/selet/2

五、修改默认账号密码(配置类)
也可以新建Spring Security配置类,注意Spring Security5.2.1版本,配置密码要用BCryptPasswordEncoder加密,不过登录还是明文,Spring Security不同版本各有差别,详情配置还是参考官方文档
@Configuration // 设置为配置类,变成Spring Bean
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception { //auth.inMemoryAuthentication()auth.inMemoryAuthentication().withUser("nicky").password(bcryptPasswordEncoder().encode("123456")).roles("admin").and().withUser("rocky").password(bcryptPasswordEncoder().encode("123456")).roles("admin");}@Beanpublic PasswordEncoder bcryptPasswordEncoder() {return new BCryptPasswordEncoder();}
}
启动项目,在浏览器中访问localhost:8080/user/selet/2,会自动跳转到localhost:8080/login,账号是nicky,密码在123

输入账号密码,跳转到我们原来请求的内容localhost:8080/user/selet/2

六、Spring Security的三个configure方法
Spring Security通过继承WebSecurityConfigurationAdapter这个类,可以选择实现该类中的三个重载的configure方法
configure(AuthenticationManagerBuilder auth):用来记录账号,密码,角色信息。
AuthenticationManagerBuilder allows public void configure(AuthenticationManagerBuilder auth) {auth.inMemoryAuthentication().withUser("user").password("password").roles("USER").and().withUser("admin").password("password").roles("ADMIN","USER");
}
configure(HttpSecurity http):(授权)配置 URL 访问权限,对应用户的权限
protected void configure(HttpSecurity http) throws Exception {http//任何请求都必须经过身份验证.authorizeUrls().antMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated();
configure(WebSecurity):一般用于配置忽略掉的 URL 地址,一般用于js,css,图片等静态资源
public void configure(WebSecurity web) throws Exception {web//web.ignoring() 用来配置忽略掉的 URL 地址,一般用于静态文件.ignoring().antMatchers("/resources/**");
}
七、Spring Security的三种身份的验证
1. 默认身份验证
在pom.xml文件映入SpringSecutrity依赖启动器,启动项目,访问文章列表页面时,出现默认的登录页,需要用默认用户名:user,密码源于控制台输出,也就是最基础的登录
2. 内存身份验证
自定义用户名和密码(用户名和密码是写在代码内,不好维护)
@Configuration // 设置为配置类,变成Spring Bean
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("nicky").password(bcryptPasswordEncoder().encode("123456")).roles("admin").and().withUser("rocky").password(bcryptPasswordEncoder().encode("123456")).roles("admin");}@Beanpublic PasswordEncoder bcryptPasswordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.headers().frameOptions().disable();//开启运行iframe嵌套页面//任何请求都必须经过身份验证http.authorizeRequests().anyRequest().authenticated();http.authorizeRequests().antMatchers("/vip/vip0/**").hasRole("vip0").antMatchers("/vip/vip1/**").hasRole("vip1").antMatchers("/vip/vip2/**").hasRole("vip2").antMatchers("/vip/vip3/**").hasRole("vip3");//开启表单验证http.formLogin().and().formLogin()//开启表单验证.loginPage("/toLogin")//跳转到自定义的登录页面.usernameParameter("name")//自定义表单的用户名的name,默认为username.passwordParameter("pwd")//自定义表单的密码的name,默认为password.loginProcessingUrl("/doLogin")//表单请求的地址,一般与form的action属性一致.successForwardUrl("/index")//登录成功后跳转的页面(重定向).failureForwardUrl("/toLogin")//登录失败后跳转的页面(重定向).and().logout()//开启注销功能.logoutSuccessUrl("/toLogin")//注销后跳转到哪一个页面.logoutUrl("/logout") // 配置注销登录请求URL为"/logout"(默认也就是 /logout).clearAuthentication(true) // 清除身份认证信息.invalidateHttpSession(true) //使Http会话无效.permitAll() // 允许访问登录表单、登录接口.and().csrf().disable(); // 关闭csrf}
}
3. 数据库方式校验
实现WebSecurityConfigurerAdapter类:将身份校验方式改变为数据库方式校验,即使用UserDetailsService
/*开启安全管理配置*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@AutowiredUserDetailsServiceImpl userDetailsService;/*自定义身份认证*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {/*1. 密码编译器*/BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();/*2.使用UserDetails进行身份认证*/auth.userDetailsService(userDetailsService).passwordEncoder(encoder);}/*自定义用户权限*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll() // 表示放行“/”访问.antMatchers("/admin/**").hasAuthority("admin") // 表示admin才能访问/admin/**.antMatchers("/common/**").hasAuthority("common") // 表示common可以访问/commom/**.and().formLogin();}
}
实现UserDetailsService类:该类只有 loadUserByUsername 一个接口方法, 用于通过用户名获取用户数据. 返回 UserDetails 对象, 表示用户的核心信息 (用户名, 用户密码, 权限等信息).
注意:其实UserDetailsService就是一个Service层的类,没有大不了的,我们也可以用UserService继承UserDetailsService
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@AutowiredUserMapper userMapper;@AutowiredAuthorityMapper authorityMapper;/*根据前端登录页面传入的用户名,查询出数据库对应的用户信息和用户权限,把用户信息和权限封装成UserDetails对象,交给SpringSecurity进行身份认证*/@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();/*根据用户名查询用户信息*/User user = userMapper.selectUserByUserName(s);/*根据用户名查询权限信息*/List<Authority> authorities = authorityMapper.selectAuthorityByUserName(s);/*遍历封装用户权限*/List<SimpleGrantedAuthority> authorityList = new ArrayList<>();for (int i=0; i<authorities.size(); i++){authorityList.add(new SimpleGrantedAuthority(authorities.get(i).getAuthority()));}// 如果用户不存在if(user!=null){/*将用户名、密码、用户权限封装成UserDetails对象*/UserDetails userDetails = new User(user.getUsername(),encoder.encode(user.getPassword()),authorityList);return userDetails;}else {throw new UsernameNotFoundException("用户不存在");}}
}
编写UserMapper类:这里仅仅编写了Mapper层逻辑,至于domain与数据库sql就不再赘述了
@Mapper
public interface UserMapper {/*根据用户名去查询用户讯息*/
@Select("select * from t_user where username=#{username}")public TUser selectUserByUserName(String username);
}
@Mapper
public interface AuthorityMapper {/*根据用户名去查询用户权限*/@Select(" select a.* from t_user u,t_authority a,user_authority au where u.id=au.uid and a.id=au.aid and u.username=#{username}")
public List<Authority> selectAuthorityByUserName(String username);
}
相关文章:
【Spring Security】 入门实战
文章目录 一、基本概念二、Spring Security第一个程序三、Spring Security没有生效四、修改默认账号密码(appliction.yml)五、修改默认账号密码(配置类)六、Spring Security的三个configure方法七、Spring Security的三种身份的验…...
SpringBoot的Interceptor拦截器的简介和实际使用
拦截器(Interceptor) 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。 作用:拦截请求,在指定的方法调用前后,根据业务需要执行…...
5个面向Python高级开发者的技巧
使用这些用于自定义类行为、编写并发代码、管理资源、存储和操作数据以及优化代码性能的高级技术来探索 Python 的深度。 本文探讨了 Python 中的五个高级主题,它们可以为解决问题和提高代码的可靠性和性能提供有价值的见解和技术。从允许您在定义类时自定义类行为的…...
Nginx简介
Nginx是什么?可以做什么事情? Nginx是高性能的HTTP和反向代理的web服务器,处理高并发的能力十分强大,能经受高负载的考研,有报告表明能能支持高达50000个并发连接数。 特点 占有内存少:一万个长连接&…...
十五分钟带你学会 Electron
文章目录 什么是 Electron为什么要选择 Electron安装 Electron桌面CSDN实战Electron 基础配置Electron 进程主进程渲染进程主进程与渲染进程的区别主进程与渲染进程的通信 Electron 跨平台问题Electron 部署打包应用程序发布应用程序 Electron 跨端原理总结 什么是 Electron E…...
设计模式-结构型模式之桥接模式
2. 桥接模式 2.1. 模式动机 设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案: 第一种设计方案是为每一种形状…...
软件测试工程师为什么要写测试用例?
软件测试工程师为什么要写测试用例?相信从事软件测试行业的从业者来讲,测试用例并不陌生。因为测试用例不仅仅是一组简单的文档,它包含前提条件、输入、执行条件和预期结果等等重要内容,并且能够完成一定的测试目的和需求。下面本…...
【DAY40】VUE练习
DOS命令: DOS(Disk Operating System)是一种操作系统,它使用命令行界面(Command Prompt)进行交互。在 DOS 中,有一些常用的命令,可以用来定位目录、创建、删除、拷贝文件和目录&…...
实模式的寄存器
实模式的寄存器有8个通用寄存器,分别为AX、BX、CX、DX、SI、DI、BP和SP。通用的意思就是它们之中的大部分可以根据需要用于多种目的。 AX: accumulator,累加寄存器 BX: base,基址寄存器 CX: count,计数寄存器 SI: Source Index&am…...
【UE 控件蓝图】通过键盘选中要点击的按钮 通过Enter键点击
上一篇【UE 控件蓝图】菜单及功能实现博客已经完成了菜单的制作,但是我们只能通过鼠标来点击菜单选项,本篇博客实现的是能够通过键盘的上下键来选中按钮,然后按下“Enter”键来实现点击按钮的效果。 效果 可以看到并没有移动鼠标也可以通过…...
SSR在天猫优品大促会场的探索实践
BBC 发现其网站加载时间每增加一秒,用户便会流失 10%。为提高页面的秒开率,我们不断探索着优化策略,仅仅在浏览器领域下的优化已经满足不了我们的极致要求,开始往服务端方向不断探索。本文将讨论业务接入SSR的几个问题:…...
WPF教程(一)---创建一个WPF程序基础知识
1.前言: 这篇主要讲WPF的开发基础,介绍了如何使用Visual Studio 2019创建一个WPF应用程序。 首先说一下学习WPF的基础知识: 1) 要会一门.NET所支持的编程语言--例如C#。 2) 会一点“标准通用标记语言”:WPF窗体程序使用的XAML语…...
【C++ 四】函数、指针
函数、指针 文章目录 函数、指针前言1 函数1.1 概述1.2 函数定义1.3 函数调用1.4 值传递1.5 函数常见样式1.6 函数声明1.7 函数分文件编写1.8 函数默认参数1.9 函数占位参数1.9 函数重载1.9.1 函数重载概述1.9.2 函数重载注意事项 2 指针2.1 指针基本概念2.2 指针变量定义和使用…...
虚拟人与娱乐传媒融合,推动综艺新模式
经过多年的更新迭代和市场的推动,虚拟人技术正在逐渐迈向成熟:3D虚拟形象的制作变得越来越精致且真实,并且出现了越来越多功能丰富使用便捷的动捕设备。因此,包括综艺影视在内的诸多领域,开始尝试将虚拟人技术融入行业…...
Linux_红帽8学习笔记分享_5
Linux_红帽8学习笔记分享_5 文章目录 Linux_红帽8学习笔记分享_51. UMASK反掩码1.1如何查看反掩码umask1.2 UMASK反掩码的作用1.2.1对于目录来说1.2.2对于文件来说 1.3如何修改UMASK反掩码1.4普通用户反掩码的测试 2.whereis的使用3. SUID权限弥补(主要针对文件,所有者执行位变…...
网络编程及项目思路
计算机和计算机之间通过网络进行数据传输 常见的软件架构: C/S:客户端/服务器 画面可以做的非常精美,用户体验好需要开发客户端,也需要开发服务端用户需要下载和更新的时候太麻烦 B/S:浏览器/服务器 不需要开发客户端,只需要…...
GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相操作
写在前面 本文主要针对使用GD(兆易创新)系列的FLASH做启动配置片时,遇到的相关问题进行简单整理复盘,避免后人踩坑。 本人操作固化芯片型号为:ZYNQ7045、690T(复旦微替代型号V7 690T)。 7系列…...
通过一个小例子来看一下C语言指针 p、*p、p、*p、*p分别代表什么
前言 在C语言中,指针是非常重要的概念。指针是一个变量,其值为另一个变量的地址。使用指针可以直接访问内存中的数据,这使得C语言非常灵活和强大。在学习C语言时相比大家都已经知道了&和*的区别了,但是你知道*&p和&*…...
【内摹访谈】谈谈AI爆发前夜的B端设计
本文来自摹客产品设计团队(MPD)的设计专栏“内摹访谈”。专栏介绍:专栏名称来源于西方美学理论「内摹仿说」,意指审美活动与摹仿活动紧密相连,审美不只针对表象动作,其核心在于由物及我,从表观带…...
Redis—AOF持久化
一、AOF定义 保存写操作命令到日志的持久化方式,就是 Redis 里的 AOF(Append Only File) 持久化功能 定义:以日志的形式记录每个操作,记录写指令不记录读指令,只许追加⽂件不允许修改,AOF保存的是appendonly.aof⽂件…...
独立开发者如何借助Taotoken多模型能力打造全能AI助手应用
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 独立开发者如何借助Taotoken多模型能力打造全能AI助手应用 对于独立开发者或小型工作室而言,构建一个功能全面的AI助手…...
技术视角:分布式投票系统的异步解耦架构与多语言协同实践
技术视角:分布式投票系统的异步解耦架构与多语言协同实践 【免费下载链接】example-voting-app Example Docker Compose app 项目地址: https://gitcode.com/gh_mirrors/exa/example-voting-app 在当今企业级应用架构设计中,如何平衡高并发处理、…...
IDEA 2018.2.3 下 Maven 依赖包消失?别慌,可能是版本兼容性在作祟
IDEA 2018.2.3 下 Maven 依赖包消失的深度排查指南 当你打开一个尘封已久的老项目,准备继续维护或迁移时,突然发现IDEA的External Libraries里空空如也,只剩下孤零零的JDK包,整个项目文件一片飘红——这种场景对许多维护历史代码库…...
碧蓝航线自动化脚本:让游戏管理变得轻松高效
碧蓝航线自动化脚本:让游戏管理变得轻松高效 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研,全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 你是否厌倦了每天重…...
3个维度深度解析:UABEA如何重塑Unity资源处理生态
3个维度深度解析:UABEA如何重塑Unity资源处理生态 【免费下载链接】UABEA c# uabe for newer versions of unity 项目地址: https://gitcode.com/gh_mirrors/ua/UABEA 在Unity游戏开发和资源处理的复杂生态中,开发者常常面临一个核心挑战…...
LC正弦波振荡器原理、设计与调试:从巴克豪森判据到电路实战
1. 从直流到交流:正弦波振荡器的核心价值与分类在电子电路的世界里,我们常常需要将稳定的直流电源,转换成特定频率和幅度的交流信号。这个看似“无中生有”的过程,正是正弦波振荡器的核心使命。无论是你手机里的无线通信模块、收音…...
基于Claude API构建可编程AI智能体:从对话到自动化生产单元
1. 项目概述:从Claude中“招聘”一个AI伙伴最近在GitHub上看到一个挺有意思的项目,叫“hire-from-claude”。初看这个标题,你可能会有点摸不着头脑:Claude不是Anthropic公司开发的那个AI助手吗?怎么还能从它那里“招聘…...
藏文语音生成准确率从61.2%跃升至94.8%:ElevenLabs Fine-tuning私有数据集构建全流程(含217小时母语者录音标注规范)
更多请点击: https://intelliparadigm.com 第一章:藏文语音生成技术演进与ElevenLabs适配挑战 藏文作为具有复杂音节结构、声调隐含性及丰富上下文依赖的黏着语系文字,其语音合成长期受限于高质量标注语料稀缺、音素-音节映射不唯一、以及缺…...
[具身智能-767]:AMCL全局撒粒子重搜与局部小范围匹配,是否算法过程是相似的,不同的是:粒子的数量、覆盖的区域、最终的精度?
AMCL 全局重搜 VS 局部匹配 详细对比核心定论二者底层算法流程、运算逻辑、执行步骤 100% 完全一致,统一遵循:运动预测→观测权重计算→粒子重采样→位姿融合输出这套粒子滤波逻辑,仅在粒子分布范围、粒子总数、收敛活动区间、定位误差精度四…...
AI教材生成神器来袭!低查重工具一键搞定30万字教材编写!
利用 AI 工具高效编写教材 整理教材的知识点真的需要“精雕细琢”,最难的地方在于平衡与衔接!我们要么会担忧重要的知识点遗漏,要么又很难掌握合适的难度梯度。小学教材常常内容晦涩难懂,学生们难以理解;而高中教材往…...
