🥳🥳Welcome Huihui's Code World ! !🥳🥳
**接下来看看由辉辉所写的关于Spring Security的相关操作吧 **
一.Spring Security是什么
1.概念
Spring Security
是一个基于Spring
框架的安全性框架,可用于对Java应用程序进行身份验证、授权和其他安全性功能的添加。它不仅可以对Web应用程序进行保护,还可以保护非Web环境下的应用程序,如远程服务和命令行应用程序等。Spring Security
提供了一系列可插拔的安全性特性,如基于标记的身份验证、权限控制、单点登录、密码加密等。它还支持多种安全性协议和标准,如OAuth
、SAML
、OpenID
等,可与各种身份提供商集成。2.工作原理
权限框架一般包含两大核心模块:认证(Authentication)和鉴权(Authorization)。
- 认证:认证模块负责验证用户身份的合法性,生成认证令牌,并保存到服务端会话中(如TLS)。
- 鉴权:鉴权模块负责从服务端会话内获取用户身份信息,与访问的资源进行权限比对。
核心组件介绍:
- **
AuthenticationManager
**:管理身份验证,可以从多种身份验证方案中选择一种。- **
Authentication
**:用于验证用户的身份。- **
SecurityContextHolder
**:用于管理SecurityContext
的ThreadLocal
,以便在整个请求上下文中进行访问,方便用户访问。- **
AccessDecisionManager
**:负责对访问受保护的资源的请求进行决策(即决定是否允许用户访问资源)- **
AccessDecisionVoter
**:是AccessDecisionManager的实现组件之一,它用于对用户请求的访问受保护的资源所需要的角色或权限进行投票。- **
ConfigAttribute
**:用于表示受保护资源或URL需要的访问权限,它可以理解为是访问控制策略的一部分
二.为什么要用Spring Security
SpringBoot 没有发布之前,Shiro 应用更加广泛,因为 Shiro 是一个强大且易用的 Java 安全框架,能够非常清晰的处理身份验证、授权、管理会话以及密码加密。利用其易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。但是 Shiro 只是一个框架而已,其中的内容需要自己的去构建,前后是自己的,中间是Shiro帮我们去搭建和配置好的。
SpringBoot
发布后,随着其快速发展,
Spring Security
(前身叫做
Acegi Security
) 重新进入人们的视野。
SpringBoot
解决了
Spring Security
各种复杂的配置,
Spring Security
在我们进行用户认证以及授予权限的时候,通过各种各样的拦截器来控制权限的访问,从而实现安全,也就是说
Spring Security
除了不能脱离
Spring
,
Shiro
的功能它都有。
- 在用户认证方面,
Spring Security
框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID
和LDAP
等。- 在用户授权方面,
Spring Security
提供了基于角色的访问控制和访问控制列表(Access Control List,ACL
),可以对应用中的领域对象进行细粒度的控制。Shiro
在这个环境下实际已经不具备优势了。因为Spring这个生态链现在是太强大了。总之就是,我们使用这个框架是用来帮助我们提高系统的安全性能的,假设我们没用这个框架来做安全认证,那么我们就需要手动编写很多的代码去完成权限的功能
三.Spring Security怎么使用
0.创建项目
这里依赖可以先选这三个,后面再pom中也可以自行添加(free marker等)
1.导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- 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>
spring-boot-starter-security
包含了以下几个主要的依赖:
- spring-security-core:
Spring Security
的核心模块,提供了基于权限的访问控制以及其他安全相关功能。- spring-security-config:提供了
Spring Security
的配置实现,例如通过Java配置创建安全策略和配置Token存储等。- spring-security-web:提供了
Spring Security Web
的基本功能,例如Servlet
集成和通过HttpSecurity
配置应用程序安全策略。2.yml配置
spring: freemarker: # 设置freemarker模板后缀 suffix: .ftl # 设置freemarker模板前缀 template-loader-path: classpath:/templates/ enabled: true server: port: 8080
3.获取security默认密码
也可以自己在yml中先配置密码(因为今天使用模拟代码,没有连接数据库)
自己设置初始的默认的密码
spring: security: user: name: 自定义用户名 password: 自定义密码
4.Web安全配置类
package com.wh.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 @EnableWebSecurity public class WebSecurityConfig { @Bean public PasswordEncoder bcryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Bean public UserDetailsService userDetailsService() { //设置账户--admin--以及这个账户的角色 UserDetails admin = User.withUsername("admin") .password(bcryptPasswordEncoder().encode("1234")) .roles("ADMIN", "USER").build(); //设置账户--user--以及这个账户的角色 UserDetails user = User.withUsername("user") .password(bcryptPasswordEncoder().encode("1234")) .roles("USER").build(); return new InMemoryUserDetailsManager(admin, user); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { //配置需要处理的url http.authorizeRequests() //antMatchers指可以配置多个url permitAll使用这个方法代表其中的url都不需要进行认证 .antMatchers("/toLogin").permitAll() //antMatchers指可以配置多个url hasRolel使用这个方法代表其中的url需要是这个角色才可以访问 .antMatchers("/admin/**").hasRole("ADMIN") //antMatchers指可以配置多个url hasAnyRole使用这个方法代表其中的url只有指定了的那些角色才能访问 .antMatchers("/user/**").hasAnyRole("ADMIN", "USER") //匹配任意`url`,其他的都需要认证 .anyRequest().authenticated() //and表示后面继续追加条件 .and() //**登录formLogin**的相关设置 .formLogin() //登录进入的界面 .loginPage("/toLogin") //设置登录请求的 URL,即表单提交的 URL .loginProcessingUrl("/userLogin") .successForwardUrl("/successLogin") //登录所需要传递的参数 .usernameParameter("username") .passwordParameter("password") //and表示后面继续追加条件 .and() //退出登录的相关配置 .logout() //退出登录的url地址 .logoutUrl("/logout") //成功退出登录之后进入的界面 .logoutSuccessUrl("/"); http.csrf().disable(); //处理异常的界面(没有权限的时候所看到的界面) http.exceptionHandling().accessDeniedPage("/noAccess"); return http.build(); } }
5.controller
package com.wh.security.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class UserController { @RequestMapping("/successLogin") public String successLogin() { return "default"; } @RequestMapping("/toLogin") public String toLogin() { return "login"; } @RequestMapping("/userLogin") public String userLogin(String username, String password) { System.out.println("username=" + username + ",password=" + password); return "default"; } @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"; } @RequestMapping("/noAccess") public String noAccess() { return "accessDenied"; } }
6.总体说明
在我们没有使用web安全配置类之前,主要登录进去了,便可以访问所有的界面,但是当我们在安全配置类中配置了多用户角色访问之后,就只可以使用其中配置的用户(类比于数据库中的用户)进行登录了,我们还需要在其中配置相关页面及请求路径(登录的界面,登录的表单提交界面路径,登录成功之后进入的界面路径...),以及配置很重要的自定义异常处理器,配置了之后,当用户是没有权限去访问此页面时,就不会是纯粹的报错403等信息了,而是一个我们自定义的提示界面
①配置多用户角色访问
@Bean public UserDetailsService userDetailsService() { //设置账户--admin--以及这个账户的角色 UserDetails admin = User.withUsername("admin") .password(bcryptPasswordEncoder().encode("1234")) .roles("ADMIN", "USER").build(); //设置账户--user--以及这个账户的角色 UserDetails user = User.withUsername("user") .password(bcryptPasswordEncoder().encode("1234")) .roles("USER").build(); return new InMemoryUserDetailsManager(admin, user); }
接下来的操作都需要在创建的SecurityConfig配置类中完成(规范)
②配置相关页面及请求路径
其中有不需要进行认证的页面,比如说登录,那么我们就可以在其中进行配置。还有一些界面是需要特定的身份才可以访问的界面
//配置需要处理的url http.authorizeRequests() //antMatchers指可以配置多个url permitAll使用这个方法代表其中的url都不需要进行认证 .antMatchers("/toLogin").permitAll() //antMatchers指可以配置多个url hasRolel使用这个方法代表其中的url需要是这个角色才可以访问 .antMatchers("/admin/**").hasRole("ADMIN") //antMatchers指可以配置多个url hasAnyRole使用这个方法代表其中的url只有指定了的那些角色才能访问 .antMatchers("/user/**").hasAnyRole("ADMIN", "USER") //匹配任意`url`,其他的都需要认证 .anyRequest().authenticated()
③配置自定义登录
.and() //**登录formLogin**的相关设置 .formLogin() //登录进入的界面 .loginPage("/toLogin") //设置登录请求的 URL,即表单提交的 URL .loginProcessingUrl("/userLogin") .successForwardUrl("/successLogin") //登录所需要传递的参数 .usernameParameter("username") .passwordParameter("password")
默认的登录界面
④配置安全退出
//and表示后面继续追加条件 .and() //退出登录的相关配置 .logout() //退出登录的url地址 .logoutUrl("/logout") //成功退出登录之后进入的界面 .logoutSuccessUrl("/");
⑤配置自定义异常处理器
//处理异常的界面(没有权限的时候所看到的界面) http.exceptionHandling().accessDeniedPage("/noAccess");
四.Spring Security中的常用方法
HttpSecurity介绍
HttpSecurity
是
Spring Security
的一个核心类,用于配置应用程序的安全策略。
HttpSecurity
类通常包含许多方法,可以用于配置以下内容:
- HTTP 请求的安全策略,例如访问控制、跨站点请求伪造 (CSRF) 防护等。
- HTTP 验证的安全策略,例如基于表单、HTTP 基本身份验证、OAuth 等。
- 访问受保护资源时所需的身份验证和授权方式。
方法说明用于配置如何处理请求的授权,默认情况下所有的请求都需要进行认证和授权才能访问受保护的资源authorizeRequests()
用于配置基于表单的身份验证,包括自定义登录页面、登录请求路径、用户名和密码的参数名称、登录成功和失败的跳转等。formLogin()
用于配置基于httpBasic()
身份验证,包括定义使用的用户名和密码、HTTP Basic
名称等。realm
用于配置退出登录功能,包括定义退出登录请求的URL、注销成功后的跳转URL、清除会话、删除logout()
令牌等。Remember-Me
用于配置跨站请求伪造保护,包括定义csrf()
的名称、保存方式、忽略某些请求等。CSRF Token
用于配置会话管理,包括定义并发控制、会话失效、禁用URL重定向、会话固定保护等。sessionManagement()
用于配置rememberMe()
功能,包括定义Remember-Me
令牌的名称、有效期、加密方法、登录成功后的处理方式等。Remember-Me
用于配置自定义的异常处理,包括定义异常处理器和异常处理页面等。exceptionHandling()
用于配置HTTP响应头信息,包括定义headers()
等头信息。X-Content-Type-Options、X-XSS-Protection、Strict-Transport-Security
用于配置跨域资源共享,包括定义可访问的来源、cors()
等。Headers
用于向当前addFilter()
中添加自定义的HttpSecurity
。Filter
用于在配置中添加另一个安全规则,并将两个规则合并。and()
匹配规则:
- URL匹配
方法说明配置一个requestMatchers()
数组,参数为request Mather
对象,其RequestMatcher
规则自定义,需要的时候放在最前面,对需要匹配的的规则进行自定义与过滤match
URL权限配置authorizeRequests()
配置一个antMatchers()
的request Mather
数组,参数为string
路径格式, 直接匹配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
l/logout
登出成功后跳转的logoutSuccessUrl()
默认是url
/login?logout
logoutSuccessHandler()
登出成功处理器,设置后会把
logoutSuccessUrl
置为null
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊
版权归原作者 是辉辉啦 所有, 如有侵权,请联系我们删除。