SpringSecurity入门

前言

Spring Security是一个用于在Java应用程序中提供身份验证和授权功能的强大框架。它构建在Spring框架之上,为开发人员提供了一套灵活且全面的安全性服务,本篇将为大家带来Spring Security的详细介绍及入门

一.安全框架

在学习了解Spring Security之前先了解什么是安全框架。安全框架顾名思义,就是解决系统安全问题的框架。任何应用开发的计划阶段都应该确定一组特定的安全需求,如身份验证、授权和加密方式。不使用安全框架之前,我们需要手动处理每个资源的访问控制,针对不同的项目都需要做不同的处理,此时就会显得非常麻烦,并且低效率引起的额外开销会延缓开发周期。使用安全框架,使开发团队能够选择最适合这些需求的框架,可以通过配置的方式实现对资源的访问限制,使得开发更加的高效。

二.主流安全框架

1.Spring Security:

Spring Security是目前Java Web领域中最流行的框架之一,它提供了一系列安全级别,包括基于认证和授权的安全保护,以及各种各样的安全校验,使得开发人员可以非常容易地为应用程序添加安全保护。Spring Security也提供了一种简单易用的方式来定制其过滤器链,以适应具体的安全需求。

2.Apache Shiro:

Apache Shiro是一个易于使用的Java Web安全框架。它提供了一种简单的方式来管理应用程序中的身份验证、授权和加密。Apache Shiro可以轻松地集成到Spring中,并提供了一系列构建块,以便定制其安全性行为。

3.JSON Web Token (JWT):

(1)不是一个完整的安全框架,但是被广泛用于在客户端和服务器之间安全地传递信息。

(2)常用于身份验证和声明传递。

JWT在前面的文章有过详细介绍,这里就不过多详述

文章链接一篇文章让你了解“JWT“-CSDN博客

 三.为什么选择Spring Security

在介绍了这么多的主流安全框架,为什么要选择Spring Security

SpringBoot 没有发布之前,Shiro 应用更加广泛,因为 Shiro 是一个强大且易用的 Java 安全框架,能够非常清晰的处理身份验证、授权、管理会话以及密码加密。利用其易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。但是 Shiro 只是一个框架而已,其中的内容需要自己的去构建,前后是自己的,中间是Shiro帮我们去搭建和配置好的。

SpringBoot 发布后,随着其快速发展,Spring Security(前身叫做Acegi Security) 重新进入人们的视野。SpringBoot 解决了 Spring Security 各种复杂的配置,Spring Security 在我们进行用户认证以及授予权限的时候,通过各种各样的拦截器来控制权限的访问,从而实现安全,也就是说 Spring Security 除了不能脱离 SpringShiro 的功能它都有。

  • 在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenIDLDAP 等。

  • 在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。

而对于Shiro而言,Shiro在这个环境下实际已经不具备优势了。因为Spring这个生态链现在是太强大了。

四.SpringSecurity讲解

1.什么是SpringSecurity?

Spring Security是一个基于Spring框架的安全性框架,可用于对Java应用程序进行身份验证、授权和其他安全性功能的添加。它不仅可以对Web应用程序进行保护,还可以保护非Web环境下的应用程序,如远程服务和命令行应用程序等。Spring Security提供了一系列可插拔的安全性特性,如基于标记的身份验证、权限控制、单点登录、密码加密等。它还支持多种安全性协议和标准,如OAuthSAMLOpenID等,可与各种身份提供商集成。

2.工作原理

权限框架一般包含两大核心模块:认证(Authentication)和鉴权(Authorization)。

  • 认证:认证模块负责验证用户身份的合法性,生成认证令牌,并保存到服务端会话中(如TLS)。

  • 鉴权:鉴权模块负责从服务端会话内获取用户身份信息,与访问的资源进行权限比对。

核心组件介绍:

  • AuthenticationManager:管理身份验证,可以从多种身份验证方案中选择一种。

  • Authentication:用于验证用户的身份。

  • SecurityContextHolder:用于管理 SecurityContextThreadLocal,以便在整个请求上下文中进行访问,方便用户访问。

  • AccessDecisionManager:负责对访问受保护的资源的请求进行决策(即决定是否允许用户访问资源)

  • AccessDecisionVoter:是AccessDecisionManager的实现组件之一,它用于对用户请求的访问受保护的资源所需要的角色或权限进行投票。

  • ConfigAttribute:用于表示受保护资源或URL需要的访问权限,它可以理解为是访问控制策略的一部分

 工作步骤:

  1. 用户认证:当用户尝试访问受保护的资源时,Spring Security首先会进行用户认证。用户提供的用户名和密码将被验证,并与存储在数据库或其他身份验证来源中的用户凭据进行比较。

  2. 认证成功处理:如果用户的认证成功,Spring Security将生成一个安全上下文(SecurityContext),其中包含用户的身份信息和授权信息。这个上下文将被存储在安全上下文持有者(SecurityContextHolder)中,以供后续的请求使用。

  3. 授权处理:一旦用户通过认证,Spring Security将根据用户的角色和权限来判断用户是否有权访问请求的资源。它可以通过注解、配置文件或编程方式来配置授权规则。如果用户被授予访问资源的权限,Spring Security将允许用户继续请求。

  4. 认证失败处理:如果用户的认证失败,Spring Security将根据配置的处理方式返回响应,例如重定向到登录页面、返回错误信息等。

  5. 安全上下文传递:在整个请求处理过程中,Spring Security将安全上下文传递给其他组件,以确保每个组件都可以访问到用户的身份信息和授权信息。这样,在业务逻辑层、控制器层和视图层等各个组件中都可以使用安全上下文来进行身份验证和授权的处理。

3.快速入门

3.1 基于SpringBoot创建项目

创建SpringBoot所需要导入的依赖

<!-- freemarker -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- web -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

配置application.yml 文件

spring:freemarker:# 设置freemarker模板后缀suffix: .ftl# 设置freemarker模板前缀template-loader-path: classpath:/templates/enabled: true

3.2 配置Spring Security

导入Spring Security依赖

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

依赖详解

  • spring-security-coreSpring Security的核心模块,提供了基于权限的访问控制以及其他安全相关功能。

  • spring-security-config:提供了Spring Security的配置实现,例如通过Java配置创建安全策略和配置Token存储等。

  • spring-security-web:提供了Spring Security Web的基本功能,例如Servlet集成和通过HttpSecurity配置应用程序安全策略。

application.yml文件中配置自定义用户名和密码

spring:security:user:name: adminpassword: 123456

4.Web安全配置类

4.1HttpSecurity介绍

HttpSecuritySpring Security 的一个核心类,用于配置应用程序的安全策略。

HttpSecurity 类通常包含许多方法,可以用于配置以下内容:

  1. HTTP 请求的安全策略,例如访问控制、跨站点请求伪造 (CSRF) 防护等。

  2. HTTP 验证的安全策略,例如基于表单、HTTP 基本身份验证、OAuth 等。

  3. 访问受保护资源时所需的身份验证和授权方式。

方法说明
authorizeRequests()用于配置如何处理请求的授权,默认情况下所有的请求都需要进行认证和授权才能访问受保护的资源
formLogin()用于配置基于表单的身份验证,包括自定义登录页面、登录请求路径、用户名和密码的参数名称、登录成功和失败的跳转等。
httpBasic()用于配置基于HTTP Basic身份验证,包括定义使用的用户名和密码、realm名称等。
logout()用于配置退出登录功能,包括定义退出登录请求的URL、注销成功后的跳转URL、清除会话、删除Remember-Me令牌等。
csrf()用于配置跨站请求伪造保护,包括定义CSRF Token的名称、保存方式、忽略某些请求等。
sessionManagement()用于配置会话管理,包括定义并发控制、会话失效、禁用URL重定向、会话固定保护等。
rememberMe()用于配置Remember-Me功能,包括定义Remember-Me令牌的名称、有效期、加密方法、登录成功后的处理方式等。
exceptionHandling()用于配置自定义的异常处理,包括定义异常处理器和异常处理页面等。
headers()用于配置HTTP响应头信息,包括定义X-Content-Type-Options、X-XSS-Protection、Strict-Transport-Security等头信息。
cors()用于配置跨域资源共享,包括定义可访问的来源、Headers等。
addFilter()用于向当前HttpSecurity中添加自定义的Filter
and()用于在配置中添加另一个安全规则,并将两个规则合并。

匹配规则:

  • URL匹配

方法说明
requestMatchers()配置一个request Mather数组,参数为RequestMatcher对象,其match规则自定义,需要的时候放在最前面,对需要匹配的的规则进行自定义与过滤
authorizeRequests()URL权限配置
antMatchers()配置一个request Matherstring数组,参数为ant路径格式, 直接匹配url
anyRequest()匹配任意url,无参 ,最好放在最后面

  • 保护URL

方法说明
authenticated()保护Url,需要用户登录
permitAll()指定URL无需保护,一般应用与静态资源文件
hasRole(String role)限制单个角色访问
hasAnyRole(String… roles)允许多个角色访问
access(String attribute)该方法使用 SPEL, 所以可以创建复杂的限制
hasIpAddress(String ipaddressExpression)限制IP地址或子网

  • 登录formLogin

方法说明
loginPage()设置登录页面的 URL
defaultSuccessUrl()设置登录成功后的默认跳转页面
failuerHandler()登录失败之后的处理器
successHandler()登录成功之后的处理器
failuerUrl()登录失败之后系统转向的url,默认是this.loginPage + “?error”
loginProcessingUrl()设置登录请求的 URL,即表单提交的 URL
usernameParameter()设置登录表单中用户名字段的参数名,默认为 username
passwordParameter()设置登录表单中密码字段的参数名,默认为 password

  • 登出logout

方法说明
logoutUrl()登出url , 默认是/logoutl
logoutSuccessUrl()登出成功后跳转的 url 默认是/login?logout
logoutSuccessHandler()登出成功处理器,设置后会把logoutSuccessUrl 置为null

4.2 自定义登录

1.创建SecurityConfig配置类

创建WebSecurityConfig配置类,设置@EnableWebSecurity注解开启Spring Security的默认行为。

package com.yu.security.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;@Configuration //声明为配置类,与Spring绑定一起启动
@EnableWebSecurity //开启SpringSecurity的默认行为
public class WebSecurityConfig {@Beanpublic PasswordEncoder bcryptPasswordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic UserDetailsService userDetailsService() {UserDetails admin = User.withUsername("admin").password(bcryptPasswordEncoder().encode("123456")).roles("ADMIN", "USER").build();UserDetails user = User.withUsername("user").password(bcryptPasswordEncoder().encode("123456")).roles("USER").build();return new InMemoryUserDetailsManager(admin, user);}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/toLogin").permitAll().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasAnyRole("ADMIN", "USER").anyRequest().authenticated().and().formLogin().loginPage("/toLogin").loginProcessingUrl("/userLogin").usernameParameter("username").passwordParameter("password").and().logout().logoutUrl("/logout").logoutSuccessUrl("/");return http.build();}}
2.创建Controller

控制路由

@Controller
public class UserController {@RequestMapping("/toLogin")public String toLogin(){return "login";}@RequestMapping("/userLogin")public String userLogin(String username,String password){System.out.println("username="+username+",password="+password);return "index";}@RequestMapping("/admin/toAddUser")public String toAddUser(){return "admin/addUser";}@RequestMapping("/admin/toListUser")public String toListUser(){return "admin/listUser";}@RequestMapping("/admin/toResetPwd")public String toResetPwd(){return "admin/resetPwd";}@RequestMapping("/admin/toUpdateUser")public String toUpdateUser(){return "admin/updateUser";}@RequestMapping("/user/toUpdatePwd")public String toUpdatePwd(){return "user/updatePwd";}
}
3.登录模板页面
<h1>用户登录</h1>
<form action="/userLogin" method="post"><label>用户:</label><input type="text" name="username"/><br/><label>密码:</label><input type="password" name="password"/><br/><input type="submit" value="登录"/>
</form>
4.配置多角色访问

在application.yml文件进行配置

spring:freemarker:suffix: .ftltemplate-loader-path: classpath:/templates/enabled: true
5.配置自定义异常处理器

修改SecurityConfig配置类,添加自定义异常处理,并设置异常处理页面。

http.exceptionHandling().accessDeniedPage("/noAccess");

当我们做权限管理时,普通用户误操作其他管理员界面,会进行异常跳转页面处理,这个要根据实际情况实际考虑

4.3异常小结

重启项目,跳转登录页重新登录。这时发现登录不成功,后台控制台也没有产生任何异常信息,通过浏览器的网络(network)查看现实登录请求接口302错误。

解决方案:关闭csrf

修改SecurityConfig配置类,添加关闭csrf配置。

http.csrf().disable();

 总结:

Spring Security可以很好得保证我们的安全性问题,但是在本次的自定义登录中还是要注意:

1.因为使用的是模拟登录,所以在实际操作创建用户时还是要按正规程序执行,并将限制用户进行传参验证

2.在Controller层中配置创建路由时,要注意路由名称,配置模板信息要与yml配置文件一致

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

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

相关文章

MeterSphere files 任意文件读取漏洞复现 (CVE-2023-25573)

0x01 产品简介 MeterSphere 是一站式开源持续测试平台, 涵盖测试跟踪、接口测试、UI 测试和性能测试等功能,全面兼容 JMeter、Selenium 等主流开源标准。 0x02 漏洞概述 MeterSphere /api/jmeter/download/files 路径文件存在文件读取漏洞,攻击者可通过该漏洞读取系统重要…

[总线仲裁]

目录 一. 集中仲裁方式1.1 链式查询方式1.2 计数器查询方式1.3 独立请求方式 二. 分布式仲裁方式 总线仲裁是为了解决多个设备争用总线这个问题 \quad 一. 集中仲裁方式 \quad 集中仲裁方式: 就像是霸道总裁来决定谁先获得总线控制权 分布仲裁方式: 商量着谁先获得总线控制权 …

国产670亿参数的DeepSeek:超越Llama2,全面开源

模型概述 DeepSeek&#xff0c;一款国产大型语言模型&#xff08;LLM&#xff09;&#xff0c;凭借其670亿参数的规模&#xff0c;正引领着人工智能领域的新浪潮。这款模型不仅在多项中英文公开评测榜单上超越了700亿参数的Llama 2&#xff0c;而且在推理、数学和编程能力方面…

JDK各个版本特性讲解-JDK16特性

JDK各个版本特性讲解-JDK16特性 一、JAVA16概述二、语法层面变化1.JEP 397&#xff1a;密封类&#xff08;第二次预览&#xff09;2.JEP 394&#xff1a;instanceof 的模式匹配3.JEP 395&#xff1a;记录4_JEP 390&#xff1a;基于值的类的警告 三、API层面变化1.JEP 338&#…

(备战2024)三天吃透Java面试八股文,面试通过率高达90%

什么样的求职者能够获得面试官的青睐&#xff1f;求职者需要准备哪些内容来面对形形色色的面试官&#xff1f;这两份资料是我在几十场面试中被面试官问到的问题&#xff0c;比其他复制粘贴的面试题强一百倍&#xff0c;堪称全网最强&#xff08;我不太喜欢“全网最强”这样的字…

车辆违规开启远光灯检测系统:融合YOLO-MS改进YOLOv8

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着社会的不断发展和交通工具的普及&#xff0c;车辆违规行为成为了一个严重的问题。其中&#xff0c;车辆违规开启远光灯是一种常见的违规行为&#xff0c;给其…

贝蒂快扫雷~(C语言)

✨✨欢迎大家来到贝蒂大讲堂✨✨ ​​​​&#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;贝蒂的游戏 贝蒂的主页&#xff1a;Betty‘s blog 引言&#xff1a; 扫雷相信大家小时候到玩过吧&#xff0c;那…

数据库故障Waiting for table metadata lock

场景&#xff1a;早上来发现一个程序&#xff0c;链接mysql数据库有点问题&#xff0c;随后排查&#xff0c;因为容器在k8s里面。所以尝试重启了pod没有效果 一、重启pod: 这里是几种在Kubernetes中重启Pod的方法: 删除Pod,利用Deployment重建 kubectl delete pod mypodDepl…

python爬虫进阶篇:利用Scrapy爬取同花顺个股行情并发送邮件通知

一、前言 上篇笔记我记录了scrapy的环境搭建和项目创建和第一次demo测试。本篇我们来结合现实场景利用scrapy给我们带来便利。 有炒股或者其它理财产品的朋友经常会关心每日的个股走势&#xff0c;如果结合爬虫进行实时通知自己&#xff0c;并根据自己预想的行情进行邮件通知&…

跟着我学Python进阶篇:01.试用Python完成一些简单问题

往期文章 跟着我学Python基础篇&#xff1a;01.初露端倪 跟着我学Python基础篇&#xff1a;02.数字与字符串编程 跟着我学Python基础篇&#xff1a;03.选择结构 跟着我学Python基础篇&#xff1a;04.循环 跟着我学Python基础篇&#xff1a;05.函数 跟着我学Python基础篇&#…

Nodejs 第三十章(防盗链)

防盗链&#xff08;Hotlinking&#xff09;是指在网页或其他网络资源中&#xff0c;通过直接链接到其他网站上的图片、视频或其他媒体文件&#xff0c;从而显示在自己的网页上。这种行为通常会给被链接的网站带来额外的带宽消耗和资源浪费&#xff0c;而且可能侵犯了原始网站的…

听一些大神说测试前途是IT里最差的,真的是这样吗?

一&#xff1a;行业经历 测试行业爬模滚打7年&#xff0c;从点点点的功能测试到现在成为高级测试&#xff0c;工资也翻了几倍&#xff1b;个人觉得&#xff0c;测试的前景并不差&#xff0c;只要自己肯努力&#xff1b;我刚出来的时候是在鹅厂做外包的功能测试&#xff0c;天天…

ROS通信频率变慢、低于设定值的解决方法

1 问题 ROS gazebo以100Hz的频率发消息&#xff0c;触发A节点的回调函数&#xff0c;进而回调函数发送新消息到B节点。理论上新消息的频率也应该是100Hz。但是用rqt_topic查看发现&#xff0c;频率只有30多Hz。 2 解决 在初始化Subscriber的时候加上ros::TransportHints().…

【halcon深度学习之那些封装好的库函数】determine_dl_model_detection_param

determine_dl_model_detection_param 目标检测的数据准备过程中的有一个库函数determine_dl_model_detection_param “determine_dl_model_detection_param” 直译为 “确定深度学习模型检测参数”。 这个过程会自动针对给定数据集估算模型的某些高级参数&#xff0c;强烈建议…

C++命名空间(超详细)using namespace std

文章目录 前言一、为什么要有命名空间二、命名空间的定义1.正常定义2.嵌套定义3.多文件 三、命名空间的使用1.命名空间名称作用域限定符2.使用using将命名空间某个成员引入3.使用using namespace将整个命名空间引入 四、c标准库总结 前言 在本文章中&#xff0c;我们将要详细介…

Linux服务器nginx部署Vue前端(详细版)

提示&#xff1a;适用于前后端项目的部署 文章目录 前言一、打包前端文件二、下载和部署Nginx三、配置conf文件启动nginx 前言 搜索到这篇文章想必你已经对Nginx比较了解&#xff0c;我也不对Nginx进行介绍赘述了&#xff0c;只需要明白Nginx本身也是一个静态资源的服务器&…

23种设计模式【创建型模式】详细介绍之【原型模式】

23种设计模式【创建型模式】详细介绍之【原型模式】 设计模式的分类和应用场景总结原型模式设计模式系列&#xff1a;深入理解原型模式&#xff08;Prototype Pattern&#xff09;什么是原型模式&#xff1f;为什么使用原型模式&#xff1f;原型模式的实现方式原型模式的代码示…

Python Opencv实践 - 手部跟踪

使用mediapipe库做手部的实时跟踪&#xff0c;关于mediapipe的介绍,请自行百度。 mediapipe做手部检测的资料&#xff0c;可以参考这里&#xff1a; MediaPipe Hands: On-device Real-time Hand Tracking 论文阅读笔记 - 知乎论文地址&#xff1a; https://arxiv.org/abs/2006…

Echarts自定义样式实现3D柱状图-长方体-圆柱体,两种样式

Echarts自定义样式实现3D柱状图-长方体-圆柱体&#xff0c;两种样式 效果图代码series配置项目 效果图 长方体 柱状体 代码 <!--此示例下载自 https://echarts.apache.org/examples/zh/editor.html?cbar3d-dataset&gl1 --> <!DOCTYPE html> <html lang…