目录
一.安全框架介绍
1.1 浅谈安全
作为企业级应用,都存在着各式各样的认证(用户基本信息认证、第三方认证、LDAP认证)与权限(访问权限、数据权限)需求,他们作为系统整体架构的基础建设部分,决定了产品的稳定性与安全性。随着技术的发展,针对系统攻击的各种技术以及机器性能不断提升,在社区中也催生了大量的安全框架,其中 Shiro 和 Spring Security 就是 J2EE 方向典型的代表。
Spring 是非常流行和成功的 Java 应用开发框架, Spring Security 正是 Spring 家族中的成员。 Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。
正如你可能知道的关于安全方面的两个主要区域是“认证” 和“授权” (或者访问控制), 一般来说, Web 应用的安全性包括用户认证( Authentication)和用户授权( Authorization) 两个部分, 这两点也是 Spring Security 重要核心功能。
-
用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。 通俗点说就是系统认为用户是否能登录。
-
用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。 通俗点讲就是系统判断用户是否有权限去做某些事情。
1.2 Spring Security简介
Spring 框架已经作为企业级应用开发的事实上的标准,而作为 Spring 的 亲儿子
、专注于企业级应用安全领域的 Spring Security 从出生开始自然备受关注。Spring Security 在诞生之后,由于其对Spring框架的无缝集成、灵活度高、场景多样化以及对OAuth标准的实现,能够满足企业在认证和授权上的各种需求;
作为 Apache 的顶级项目的 Shiro 差不多能够满足企业级应用系统对于安全性以及稳定性的要求,但是因为出身的问题,关注度持续走低。其关注度以及市场使用率远远不及 Spring Security。
二、认证一下认证和授权
认证: 解决你是认证的问题.
授权: 当前你的身份能干点啥的问题
基于角的访问控制: (RBAC)
系统当中,有两种类型的资源:
公共资源
认证的资源
三、spring security 基本使用
3.1 官方文档
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements
3.2 测试环境搭建
新建一个spring boot工程.
直接引入spring-boot-starter-security
测试一下.
从控制台当中,输出一个密码;
3.3 疑问
如何进行密码和用户密码验证的.
页面是哪里来的,过滤器当中定义的
密码能不能修改一下.
spring security的组成, 由15个过滤器组成的, 形成一个过滤器链.
15个默认的过滤器
2023-09-13 09:54:05.456 INFO 11164 --- [ restartedMain] .SpringBootSecurityDemo01Application : Started SpringBootSecurityDemo01Application in 1.393 seconds (JVM running for 2.129)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@6a79d705
1
org.springframework.security.web.context.SecurityContextPersistenceFilter@38f55ca9
2
org.springframework.security.web.header.HeaderWriterFilter@2fd33922
3
org.springframework.security.web.csrf.CsrfFilter@7b9dab27
4
org.springframework.security.web.authentication.logout.LogoutFilter@1e352b6
// 重要
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@59d29c7a
// 默认的页面的地方
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@42b4e138
7
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@591dc942
8
org.springframework.security.web.authentication.www.BasicAuthenticationFilter@4bb3c6bf
9
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@645f9658
10
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@2130860c
11
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@cce7ae0
12
org.springframework.security.web.session.SessionManagementFilter@6fd7a2fc
// 认证出现异常由它处理
org.springframework.security.web.access.ExceptionTranslationFilter@34767f7f
14
org.springframework.security.web.access.intercept.FilterSecurityInterceptor@5131977f
SecurityAutoConfiguration
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Security.
*
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
// 导入了security默认的配置.
@EnableConfigurationProperties(SecurityProperties.class)
@Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
SecurityDataConfiguration.class, ErrorPageSecurityFilterConfiguration.class })
public class SecurityAutoConfiguration {
@Bean
@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {
return new DefaultAuthenticationEventPublisher(publisher);
}
}
SecurityProperties.java
@ConfigurationProperties(prefix = "spring.security")
public class SecurityProperties {
public static class User {
/**
* Default user name.
*/
private String name = "user";
/**
* Password for the default user name.
*/
private String password = UUID.randomUUID().toString();
/**
* Granted roles for the default user name.
*/
private List<String> roles = new ArrayList<>();
}
}
3.4 资源访问控制
spring security默认的会认证所有的资源.如果要放行几个,或者不需要认证的接口,则我们必须告诉spring boot.
package com.tingyi.configs;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author 听忆
*/
@Configuration
public class SecurityOldConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// /tingyi, 不需要认证.
// /hello,需要认证的.
http.authorizeRequests() // 获取所有的认证请求
.mvcMatchers("/tingyi").permitAll() // 如果请求的路径当中,有/tingyi, permitAll表示放行操作
.anyRequest().authenticated() // 除此之外,其它任何资源的访问都需要经过认证.
.and()
.formLogin() // 表单验证
.and()
.csrf().disable(); // 关闭跨站访问
}
}
第二种配置方式;
package com.tingyi.configs;
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.web.SecurityFilterChain;
/**
* @author 听忆
*/
@Configuration
public class SecurityConfig {
// @Bean
// public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//
// return http.authorizeRequests()
// .mvcMatchers("/tingyi")
// .permitAll()
// .anyRequest()
// .authenticated()
// .and()
// .formLogin()
// .and()
// .csrf().disable()
// .build();
// }
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.authorizeRequests(
authorize -> authorize.mvcMatchers("/tingyi")
.permitAll()
.anyRequest()
.authenticated())
.formLogin()
.and()
.csrf(csrf -> csrf.disable())
.build();
}
}
3.5 自动装配
SecurityAutoConfiguration.java
SecurityProperties.java
如果说我当前没有自定义的配置文件,也就是没有写: SecurityConfig.java,那么此时会执行默认的配置. 由spring boot搞好的.
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Security.
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Madhura Bhave
* @since 1.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
// 导入配置类
@EnableConfigurationProperties(SecurityProperties.class)
// 导入其它配置文件.
// SpringBootWebSecurityConfiguration.class
// WebSecurityEnablerConfiguration.class
@Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
SecurityDataConfiguration.class, ErrorPageSecurityFilterConfiguration.class })
public class SecurityAutoConfiguration {
@Bean
@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {
return new DefaultAuthenticationEventPublisher(publisher);
}
}
SpringBootWebSecurityConfiguration
@Configuration(proxyBeanMethods = false)
// 默认的Web配置.
@ConditionalOnDefaultWebSecurity
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
return http.build();
}
}
@ConditionalOnDefaultWebSecurity
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(DefaultWebSecurityCondition.class)
public @interface ConditionalOnDefaultWebSecurity {
}
DefaultWebSecurityCondition.class
/**
* {@link Condition} for
* {@link ConditionalOnDefaultWebSecurity @ConditionalOnDefaultWebSecurity}.
*
* @author Phillip Webb
*/
class DefaultWebSecurityCondition extends AllNestedConditions {
DefaultWebSecurityCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })
static class Classes {
}
// 默认配置不生效,则需要满足的条件:
@ConditionalOnMissingBean({ WebSecurityConfigurerAdapter.class, SecurityFilterChain.class })
static class Beans {
}
}
两种配置方案都可以使用,前提条件security源码不修改.
3.6 默认的认证流程
@Configuration(proxyBeanMethods = false)
@ConditionalOnDefaultWebSecurity
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
// 这个表示, 对所有的到请求都要认证.
// 认证的姿势: 表单
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
return http.build();
}
}
UsernamePasswordAuthencationFitler. –> 使用用户名称和密码进行认证.
AbstractAuthenticationProcessingFilter –> 它是: UsernamePasswordAuthencationFitlerr 父类.
UsernamePasswordAuthenticationToken, 将我们收到的「从前端或者客户端传递过来的用户名称和密码」, 封装成对象,最后要交给AuthenticaitonManager.
AuthenticationManger, 接口,表示认证管理器.有一个认证方法.:
Authentication
ProviderManager
AuthenticationProvider
AbstractUserDetailsAuthenticationProvider
UserDetails
User对象