当前位置: 首页 > 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;能够为…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...