当前位置: 首页 > news >正文

Spring Security 快速开始

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

一、认证

1、从数据中读数据完成认证

@Service
public class MyUserDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws AuthenticationException {MyUser myUser;// 这里模拟从数据库中获取用户信息if (username.equals("admin")) {myUser = new MyUser("admin", new BCryptPasswordEncoder().encode("123456"), new ArrayList<>(Arrays.asList("p1", "p2")));return myUser;} else {throw new UsernameNotFoundException("用户不存在");}}
}

集成User可以补充一些自己的数据,修改构造方法(或者直接使用User)

public class MyUser extends User {private int sex;private int age;private String address;public MyUser(String username, String password, List<String> authorities) {super(username, password, authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));}public int getSex() {return sex;}public void setSex(int sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}

相关配置

@Configuration
public class MySecurityConfigurer extends WebSecurityConfigurerAdapter {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}

2、实现同时多种认证方式

在1的基础上添加相关配置

/*** 手机验证码认证信息,在UsernamePasswordAuthenticationToken的基础上添加属性 手机号、验证码*/
public class MobilecodeAuthenticationToken extends AbstractAuthenticationToken {private static final long serialVersionUID = 530L;private Object principal;private Object credentials;private String phone;private String mobileCode;public MobilecodeAuthenticationToken(String phone, String mobileCode) {super(null);this.phone = phone;this.mobileCode = mobileCode;this.setAuthenticated(false);}public MobilecodeAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {super(authorities);this.principal = principal;this.credentials = credentials;super.setAuthenticated(true);}public Object getCredentials() {return this.credentials;}public Object getPrincipal() {return this.principal;}public String getPhone() {return phone;}public String getMobileCode() {return mobileCode;}public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {if (isAuthenticated) {throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");} else {super.setAuthenticated(false);}}public void eraseCredentials() {super.eraseCredentials();this.credentials = null;}
}
public class MobilecodeAuthenticationProvider implements AuthenticationProvider {private UserDetailsService userDetailsService;@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {MobilecodeAuthenticationToken mobilecodeAuthenticationToken = (MobilecodeAuthenticationToken) authentication;String phone = mobilecodeAuthenticationToken.getPhone();String mobileCode = mobilecodeAuthenticationToken.getMobileCode();System.out.println("登陆手机号:" + phone);System.out.println("手机验证码:" + mobileCode);// 模拟从redis中读取手机号对应的验证码及其用户名Map<String,String> dataFromRedis = new HashMap<>();dataFromRedis.put("code", "6789");dataFromRedis.put("username", "admin");// 判断验证码是否一致if (!mobileCode.equals(dataFromRedis.get("code"))) {throw new BadCredentialsException("验证码错误");}// 如果验证码一致,从数据库中读取该手机号对应的用户信息MyUser loadedUser = (MyUser) userDetailsService.loadUserByUsername((String)dataFromRedis.get("username"));if (loadedUser == null) {throw new UsernameNotFoundException("用户不存在");} else {MobilecodeAuthenticationToken result = new MobilecodeAuthenticationToken(loadedUser, null, loadedUser.getAuthorities());return result;}}@Overridepublic boolean supports(Class<?> aClass) {return MobilecodeAuthenticationToken.class.isAssignableFrom(aClass);}public void setUserDetailsService(UserDetailsService userDetailsService) {this.userDetailsService = userDetailsService;}
}

修改配置文件

@Configuration
public class MySecurityConfigurer extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService myUserDetailsService;@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic MobilecodeAuthenticationProvider mobilecodeAuthenticationProvider() {MobilecodeAuthenticationProvider mobilecodeAuthenticationProvider = new MobilecodeAuthenticationProvider();mobilecodeAuthenticationProvider.setUserDetailsService(myUserDetailsService);return mobilecodeAuthenticationProvider;}@Beanpublic DaoAuthenticationProvider daoAuthenticationProvider() {DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());daoAuthenticationProvider.setUserDetailsService(myUserDetailsService);return daoAuthenticationProvider;}/*** 定义认证管理器AuthenticationManager* @return*/@Beanpublic AuthenticationManager authenticationManager() {List<AuthenticationProvider> authenticationProviders = new ArrayList<>();authenticationProviders.add(mobilecodeAuthenticationProvider());authenticationProviders.add(daoAuthenticationProvider());ProviderManager authenticationManager = new ProviderManager(authenticationProviders);
//        authenticationManager.setEraseCredentialsAfterAuthentication(false);return authenticationManager;}@Overridepublic void configure(HttpSecurity http) throws Exception {http// 关闭csrf.csrf().disable()// 权限配置,登录相关的请求放行,其余需要认证.authorizeRequests().antMatchers("/login/*").permitAll().anyRequest().authenticated();}
}

发送登录请求

@RestController
@RequestMapping("/login")
public class TestController {@GetMapping("/hello")public String hello(){return "Hello Spring security";}@Autowiredprivate AuthenticationManager authenticationManager;/*** 用户名密码登录* @param username* @param password* @return*/@GetMapping("/usernamePwd")public Result usernamePwd(String username, String password) {UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, password);Authentication authenticate = null;try {authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);} catch (Exception e) {e.printStackTrace();return Result.error("登陆失败");}String token = UUID.randomUUID().toString().replace("-", "");return Result.ok(token);}/*** 手机验证码登录* @param phone* @param mobileCode* @return*/@GetMapping("/mobileCode")public Result mobileCode(String phone, String mobileCode) {MobilecodeAuthenticationToken mobilecodeAuthenticationToken = new MobilecodeAuthenticationToken(phone, mobileCode);Authentication authenticate = null;try {authenticate = authenticationManager.authenticate(mobilecodeAuthenticationToken);} catch (Exception e) {e.printStackTrace();return Result.error("验证码错误");}String token = UUID.randomUUID().toString().replace("-", "");return Result.ok(token);}
}

 3、用token 校验过滤

 认证成功后通常会返回一个token令牌(如jwt等),后续我们将token放到请求头中进行请求,后端校验该token,校验成功后再访问相应的接口

@Component
@WebFilter
public class TokenAuthenticationFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {String token = httpServletRequest.getHeader("token");// 如果没有token,跳过该过滤器if (!StringUtils.isEmpty(token)) {// 模拟redis中的数据Map map = new HashMap();map.put("test_token1", new MyUser("admin", new BCryptPasswordEncoder().encode("123456"), new ArrayList<>(Arrays.asList("p1", "p2"))));map.put("test_token2", new MyUser("root", new BCryptPasswordEncoder().encode("123456"), new ArrayList<>(Arrays.asList("p1", "p2"))));// 这里模拟从redis获取token对应的用户信息MyUser myUser = (MyUser)map.get(token);if (myUser != null) {UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(myUser, null, myUser.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authRequest);} else {throw new PreAuthenticatedCredentialsNotFoundException("token不存在");}}filterChain.doFilter(httpServletRequest, httpServletResponse);}
}

 修改配置 MySecurityConfigurer

    @Overridepublic void configure(HttpSecurity http) throws Exception {http// 关闭csrf.csrf().disable()// 权限配置,登录相关的请求放行,其余需要认证.authorizeRequests().antMatchers("/login/*").permitAll().anyRequest().authenticated().and()// 添加token认证过滤器.addFilterAfter(tokenAuthenticationFilter, LogoutFilter.class)// 不使用session会话管理.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);}

二、认证

1、基于方法的授权

当我们想要开启spring方法级安全时,只需要在任何 @Configuration实例上使用@EnableGlobalMethodSecurity 注解就能达到此目的。同时这个注解为我们提供了prePostEnabled 、securedEnabled 和 jsr250Enabled 三种不同的机制来实现同一种功能。

    @GetMapping("/hello")@PreAuthorize("hasAuthority('cece2')")public String hello(){return "Hello Spring security";}

 也可以

@PreAuthorize("@el.verify('cece2')")  然后往容器中添加el 实例,然后使用自定义的方法验证权限

2、基于Request的授权

http.authorizeRequests(authorize -> authorize// 添加授权配置.requestMatchers("/user/list").hasAnyAuthority("USER_LIST").requestMatchers("/user/add").hasAnyAuthority("USER_ADD")// 对所有请求开启授权保护.anyRequest()// 已认证的请求会被自动授权.authenticated())

三、相关配置

Security 常用配置-CSDN博客

四:参考

Spring Security入门教程

​​​​​​Spring Security 实现多种认证方式

相关文章:

Spring Security 快速开始

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency> 一、认证 1、从数据中读数据完成认证 Service public class MyUserDetailsService implements UserDeta…...

Lua5.3 参考手册

《Lua 5.3 参考手册》是对 Lua 5.3 版本语言的官方定义。这份手册详细描述了 Lua 语言的语法、语义以及标准库和 C API。它是由巴西里约热内卢 Pontifical Catholic 大学的 PUC-Rio 团队开发的&#xff0c;并且是一个自由软件&#xff0c;广泛应用于世界各地的产品和项目中【9†…...

Centos如何配置阿里云的yum仓库作为yum源?

背景 Centos在国内访问官方yum源慢&#xff0c;可以用国内的yum源&#xff0c;本文以阿里云yum源为例说明。 快速命令 sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.a…...

力扣139-单词拆分(Java详细题解)

题目链接&#xff1a;139. 单词拆分 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完背包&#xff0c;所以现在的题解都是以背包问题为基础再来写的。 如果大家不懂背包问题的话&#…...

CSS —— display属性

用于指定一个元素在页面中的显示方式 HTML中标签元素大体被分为三种类型&#xff1a;块元素、行内元素和行内块元素 块元素 &#xff1a;block 1.独占一行 2.水平方向&#xff0c;占满它父元素的可用空间&#xff08;宽度是父级的100%&#xff09; 3.垂直方向&#xff0c;占据的…...

BTC ETF资金流入暴涨400%,市场下一步将如何发展?

近期&#xff0c;BTC现货ETF&#xff08;交易所交易基金&#xff09;市场出现了显著的资金流入&#xff0c;尤其是在9月10日&#xff0c;BTC ETF吸引了近1.17亿美元的资金流入&#xff0c;相较于前一天的3729万美元&#xff0c;暴涨了400%。这种现象引发了市场广泛关注&#xf…...

视频监控管理平台LntonAIServer视频智能分析抖动检测算法应用场景

在视频监控系统中&#xff0c;视频画面的稳定性对于确保监控效果至关重要。抖动现象是指视频画面中存在不稳定或频繁晃动的情况&#xff0c;这可能会影响视频的清晰度和可读性。LntonAIServer通过引入抖动检测功能&#xff0c;帮助用户及时发现并解决视频流中的抖动问题&#x…...

初识php库管理工具composer的体验【爽】使用phpword模板功能替换里面的字符串文本

需求&#xff1a; 做了一个租赁的项目&#xff0c;里面要求签署个人授权协议&#xff0c;里面要填写姓名&#xff0c;手机号&#xff0c;身份证号&#xff0c;签署日期等参数&#xff0c;格式如下图 格式&#xff1a; 如上图&#xff0c;word中的字符串模板变量使用${varname…...

每日一问:C++ 如何实现继承、封装和多态

每日一问&#xff1a;C 如何实现继承、封装和多态 C 是一门面向对象编程语言&#xff0c;通过继承、封装和多态这三个核心特性实现了对复杂系统的高效管理和扩展。继承让代码重用性得以提升&#xff0c;封装保护数据的完整性&#xff0c;而多态通过不同的接口实现了灵活性。本文…...

STM32常用数据采集滤波算法

例如&#xff0c;STM32进行滤波处理时&#xff0c;主要目的是处理数据采集过程中可能产生的噪声和尖刺信号。这些噪声可能来自电源干扰、传感器自身的不稳定性或其他外部因素。 1.一阶互补滤波 方法&#xff1a;取a0~1,本次滤波结果&#xff08;1-a&#xff09;本次采样值a上…...

二分系列(二分查找)9/12

一、分情况讨论 1.左闭右闭:[left,right] 因为是左闭右闭&#xff0c;所以left和right都能直接取到。 #这里将>放到一起&#xff0c;当nums[mid]>target的时候&#xff0c; 要更新右边界&#xff0c;rightmid-1,这样就把一些相同的情况也切出去了 可以理解为找的第一个…...

如何通过可视化大屏,助力智慧城市的“城市微脑”建设?

在智慧城市的宏伟蓝图中&#xff0c;常常面临着一个关键挑战&#xff1a;如何确保这些理念和技术能够真正地惠及城市的每一个角落&#xff0c;每一个产业&#xff0c;以及每一位市民。问题的核心在于城市的具体应用场景&#xff0c;无论是横向的社区、园区、镇街、学校、酒店、…...

何时空仓库

某仓库现存货物 s 箱&#xff0c;每天上午出货 m 箱、下午进货 n 箱&#xff0c;若s≥m>n≥0&#xff0c;则第 k 天将会出现空仓的情况。请你帮仓库管理员编写程序&#xff0c;输入s、m 和 n&#xff0c;计算并输出 k。 输入格式 s,m,n (s≥m>n≥0) 输出格式 k 输入样例…...

美创获评CNVD年度原创漏洞发现贡献单位!

9月10日&#xff0c;第21届中国网络安全年会暨网络安全协同治理分论坛在广州成功举办。会上&#xff0c;美创科技首次获评“CNVD年度原创漏洞发现贡献单位”。 美创科技依托第59号安全实验室&#xff0c;专注数据安全技术和攻防研究。凭借深厚的技术积累与优势&#xff0c;被遴…...

Spring 循环依赖原理及解决方案

一、什么是循环依赖 循环依赖指的是一个实例或多个实例存在相互依赖的关系&#xff08;类之间循环嵌套引用&#xff09;。 举例&#xff1a; Component public class AService {// A中注入了BAutowiredprivate BService bService; }Component public class BService {// B中也…...

【数据结构与算法 | 灵神题单 | 插入链表篇】力扣2807, LCR 029, 147

1. 力扣2807&#xff1a;在链表中插入最大公约数 1.1 题目&#xff1a; 你一个链表的头 head &#xff0c;每个结点包含一个整数值。 在相邻结点之间&#xff0c;请你插入一个新的结点&#xff0c;结点值为这两个相邻结点值的 最大公约数 。 请你返回插入之后的链表。 两个…...

瑞芯微rv1126 Linux 系统,修改系统时区,包有效方法

在 Linux 系统中,修改时区的步骤通常包括创建符号链接到正确的时区文件,并确保相关的配置文件已正确更新。然而,某些系统可能有额外的步骤或需要修改其他配置文件来使更改生效。以下是一些步骤。 1. 创建符号链接 ln -sf /usr/share/zoneinfo/Asia/Hong_Kong /etc/localti…...

系统架构设计师:数据库设计

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 系统架构设计师:数据库设计前言数据库基础概念数据模型三要素数据库的三级模型和两级…...

代码随想录刷题day31丨56. 合并区间,738.单调递增的数字,总结

代码随想录刷题day31丨56. 合并区间&#xff0c;738.单调递增的数字&#xff0c;总结 1.题目 1.1合并区间 题目链接&#xff1a;56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 视频讲解&#xff1a;贪心算法&#xff0c;合并区间有细节&#xff01;LeetCode&#x…...

深圳建站公司-如何做网站

深圳建站公司&#xff1a;如何制作一个成功的网站 在信息化快速发展的今天&#xff0c;企业和个人越来越重视网络形象&#xff0c;网站成为了展示品牌、推广产品和服务的重要平台。深圳作为科技创新和经济发展的前沿城市&#xff0c;涌现出许多专业的建站公司&#xff0c;能够为…...

告别音频调试噩梦:AP-0316 DSP语音处理模组全解析与实战选型

在嵌入式产品开发中&#xff0c;语音处理往往是考验硬件工程师耐心的“深水区”。无论是智能门禁的对讲系统&#xff0c;还是会议终端的免提通话&#xff0c;只要涉及到麦克风阵列、回声消除&#xff08;AEC&#xff09;和环境降噪&#xff08;ENC&#xff09;&#xff0c;往往…...

LiveSplit终极指南:为速度跑者量身定制的精准计时神器

LiveSplit终极指南&#xff1a;为速度跑者量身定制的精准计时神器 【免费下载链接】LiveSplit A sleek, highly customizable timer for speedrunners. 项目地址: https://gitcode.com/gh_mirrors/li/LiveSplit LiveSplit是一款专为速度跑者打造的轻量级、高度可定制的计…...

3步解锁跨平台系统部署:WinDiskWriter让macOS用户轻松制作Windows启动盘

3步解锁跨平台系统部署&#xff1a;WinDiskWriter让macOS用户轻松制作Windows启动盘 【免费下载链接】windiskwriter &#x1f5a5; Windows Bootable USB creator for macOS. &#x1f6e0; Patches Windows 11 to bypass TPM and Secure Boot requirements. &#x1f47e; UE…...

收藏! Harness 让你轻松驾驭大模型,小白也能写出高效代码

本文探讨了 AI 编程 Agent 的核心要素&#xff0c;强调 Harness&#xff08;工具、流程和反馈系统&#xff09;的重要性远超单纯依赖模型。通过实例说明&#xff0c;优化编辑格式等 Harness 设计可显著提升 Agent 成功率。文章提出&#xff0c;为 AI 准备更好的工作台&#xff…...

酷安UWP桌面客户端:在Windows电脑上高效刷酷安的完整指南

酷安UWP桌面客户端&#xff1a;在Windows电脑上高效刷酷安的完整指南 【免费下载链接】Coolapk-UWP 一个基于 UWP 平台的第三方酷安客户端 项目地址: https://gitcode.com/gh_mirrors/co/Coolapk-UWP 还在为手机小屏幕刷酷安而感到眼睛酸痛吗&#xff1f;想在27寸大屏幕…...

Windows 11系统优化终极指南:用Win11Debloat一键清理系统垃圾,提升电脑性能

Windows 11系统优化终极指南&#xff1a;用Win11Debloat一键清理系统垃圾&#xff0c;提升电脑性能 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various ot…...

抖音批量下载终极指南:免费高效获取视频、图集、合集和音乐

抖音批量下载终极指南&#xff1a;免费高效获取视频、图集、合集和音乐 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback …...

Fastboot Enhance:Windows平台Android设备管理的终极图形化解决方案

Fastboot Enhance&#xff1a;Windows平台Android设备管理的终极图形化解决方案 【免费下载链接】FastbootEnhance A user-friendly Fastboot ToolBox & Payload Dumper for Windows 项目地址: https://gitcode.com/gh_mirrors/fa/FastbootEnhance Fastboot Enhance…...

终极指南:ChatGPT-Web-Midjourney-Proxy如何实现实时AI交互的WebSocket通信

终极指南&#xff1a;ChatGPT-Web-Midjourney-Proxy如何实现实时AI交互的WebSocket通信 ChatGPT-Web-Midjourney-Proxy是一套集成ChatGPT、Midjourney和GPTs功能的全栈UI解决方案&#xff0c;通过WebSocket技术实现了流畅的实时AI交互体验。本文将深入解析其WebSocket通信机制…...

【C++笔记】内存管理流食般投喂

声明&#xff1a;以下知识相关资料来自比特官网和小编手搓~C/C内存管理1、C/C内存分布2、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free3、C内存管理方式3.1、new/delete操作内置类型3.2、new和delete操作自定义类型4、operator new 与 operator delete 函数…...