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

Spring Security—配置(Configuration)

目录

一、Java 配置

1、Hello Web Security Java 配置

2、AbstractSecurityWebApplicationInitializer

3、不使用 Spring 的 AbstractSecurityWebApplicationInitializer

4、使用 SpringMCV 的 AbstractSecurityWebApplicationInitializer

二、HttpSecurity

三、多个 HttpSecurity 实例

四、自定义 DSL

五、后处理配置对象


一、Java 配置

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

在Spring 3.1中,Spring框架加入了对 Java configuration 的一般支持。Spring Security 3.2引入了Java配置,让用户无需使用任何XML就能配置Spring Security。

如果你熟悉 Security Namespace 配置,你应该会发现它与Spring Security Java配置之间有不少相似之处。

Spring Security 提供了 大量的示例应用程序 来演示Spring Security Java配置的使用。

1、Hello Web Security Java 配置

第一步是创建我们的Spring Security Java配置。该配置创建了一个被称为 springSecurityFilterChain 的 Servlet 过滤器,它负责应用程序中的所有安全问题(保护应用程序的URL,验证提交的用户名和密码,重定向到登录表单,等等)。下面的例子显示了Spring Security Java配置的最基本例子。

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.authentication.builders.*;
import org.springframework.security.config.annotation.web.configuration.*;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

	@Bean
	public UserDetailsService userDetailsService() {
		InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
		manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
		return manager;
	}
}

这个配置并不复杂或广泛,但它做了很多事情。

  • 要求对你的应用程序中的每个URL进行认证
  • 为你生成一个登录表单(Form)
  • 让用户使用 Username (user)和 Password(password)进行基于表单的身份验证。
  • 让用户注销
  • 防止 CSRF 攻击
  • Session Fixation 保护
  • Security Header 集成:
    • HTTP Strict Transport Security 用于安全的请求
    • X-Content-Type-Options 集成
    • 缓存控制(你可以在以后的应用程序中覆盖它,以允许对你的静态资源进行缓存。)
    • X-XSS-Protection 集成
    • 集成 X-Frame-Options integration 防止 Clickjacking(点击劫持)
  • 与以下Servlet API方法整合。
    • HttpServletRequest#getRemoteUser()
    • HttpServletRequest#getUserPrincipal()
    • HttpServletRequest#isUserInRole(java.lang.String)
    • HttpServletRequest#login(java.lang.String, java.lang.String)
    • HttpServletRequest#logout()

2、AbstractSecurityWebApplicationInitializer

下一步是在WAR文件中注册 springSecurityFilterChain。你可以在Servlet 3.0以上的环境中通过 Spring的 WebApplicationInitializer 支持 在Java配置中完成。毫不奇怪,Spring Security提供了一个基类(AbstractSecurityWebApplicationInitializer)来确保 springSecurityFilterChain 为你注册。我们使用 AbstractSecurityWebApplicationInitializer 的方式有所不同,这取决于我们是否已经在使用Spring,或者Spring Security是否是我们应用中唯一的Spring组件。

  • 不使用 Spring 的 AbstractSecurityWebApplicationInitializer - 如果你还没有使用Spring,请使用这些说明。
  • 使用 SpringMCV 的 AbstractSecurityWebApplicationInitializer - 如果你已经在使用Spring,请使用这些说明。

3、不使用 Spring 的 AbstractSecurityWebApplicationInitializer

如果你没有使用 Spring 或 Spring MVC,你需要将 WebSecurityConfig 传递给超类(superclass)以确保配置被接收。

import org.springframework.security.web.context.*;

public class SecurityWebApplicationInitializer
	extends AbstractSecurityWebApplicationInitializer {

	public SecurityWebApplicationInitializer() {
		super(WebSecurityConfig.class);
	}
}

SecurityWebApplicationInitializer:

  • 为你应用程序中的每个URL自动注册 springSecurityFilterChain 过滤器。
  • 添加一个 ContextLoaderListener,加载 WebSecurityConfig。

4、使用 SpringMCV 的 AbstractSecurityWebApplicationInitializer

如果我们在应用的其他地方使用Spring,我们可能已经有一个 WebApplicationInitializer,正在加载我们的Spring配置。如果我们使用之前的配置,我们会得到一个错误。相反,我们应该用现有的 ApplicationContext 注册Spring Security。例如,如果我们使用Spring MVC,我们的 SecurityWebApplicationInitializer 可能看起来像下面这样。

import org.springframework.security.web.context.*;

public class SecurityWebApplicationInitializer
	extends AbstractSecurityWebApplicationInitializer {

}

这只是为你应用程序中的每个URL注册 springSecurityFilterChain。之后,我们需要确保 WebSecurityConfig 被加载到我们现有的 ApplicationInitializer 中。例如,如果我们使用Spring MVC,它会被添加到 getRootConfigClasses() 中。

public class MvcWebApplicationInitializer extends
		AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { WebSecurityConfig.class };
	}

	// ... other overrides ...
}

二、HttpSecurity

到目前为止,我们的 WebSecurityConfig 只包含了关于如何验证用户的信息。Spring Security 是如何知道我们要要求所有的用户都要进行身份验证的?Spring Security 如何知道我们要支持基于表单的认证?实际上,有一个配置类(称为 SecurityFilterChain )在幕后被调用。它被配置为以下的默认实现。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
	http
		.authorizeRequests(authorize -> authorize
			.anyRequest().authenticated()
		)
		.formLogin(withDefaults())
		.httpBasic(withDefaults());
	return http.build();
}

默认配置(如上例所示):

  • 确保对我们的应用程序的任何请求都需要用户进行认证
  • 让用户通过基于表单的登录进行认证
  • 让用户用HTTP基本认证(HTTP Basic authentication)进行认证

请注意,这种配置与XML命名空间的配置是平行的。

<http>
	<intercept-url pattern="/**" access="authenticated"/>
	<form-login />
	<http-basic />
</http>

三、多个 HttpSecurity 实例

我们可以配置多个 HttpSecurity 实例,就像我们可以在XML中拥有多个 <http> 节点一样。关键是要注册多个 SecurityFilterChain @Bean。下面的例子对以 /api/ 开头的URL有不同的配置。

@Configuration
@EnableWebSecurity
public class MultiHttpSecurityConfig {
	@Bean                                                             
	public UserDetailsService userDetailsService() throws Exception {
		// ensure the passwords are encoded properly
		UserBuilder users = User.withDefaultPasswordEncoder();
		InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
		manager.createUser(users.username("user").password("password").roles("USER").build());
		manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build());
		return manager;
	}

	@Bean
	@Order(1)                                                        
	public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher("/api/**")                                   
			.authorizeHttpRequests(authorize -> authorize
				.anyRequest().hasRole("ADMIN")
			)
			.httpBasic(withDefaults());
		return http.build();
	}

	@Bean                                                            
	public SecurityFilterChain formLoginFilterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests(authorize -> authorize
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}

像往常一样配置认证。

创建一个 SecurityFilterChain 的实例,其中包含 @Order 以指定哪一个 SecurityFilterChain 应该被优先考虑。

http.securityMatcher 指出,这个 HttpSecurity 只适用于以 /api/ 开头的URL。

创建另一个 SecurityFilterChain 的实例。如果URL不是以 /api/ 开头,就会使用这个配置。这个配置被认为在 apiFilterChain 之后,因为它的 @Order 值在 1 之后(没有 @Order 默认为最后)。

四、自定义 DSL

你可以在 Spring Security 中提供你自己的自定义DSL。

  • Java
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
	private boolean flag;

	@Override
	public void init(HttpSecurity http) throws Exception {
		// any method that adds another configurer
		// must be done in the init method
		http.csrf().disable();
	}

	@Override
	public void configure(HttpSecurity http) throws Exception {
		ApplicationContext context = http.getSharedObject(ApplicationContext.class);

		// here we lookup from the ApplicationContext. You can also just create a new instance.
		MyFilter myFilter = context.getBean(MyFilter.class);
		myFilter.setFlag(flag);
		http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
	}

	public MyCustomDsl flag(boolean value) {
		this.flag = value;
		return this;
	}

	public static MyCustomDsl customDsl() {
		return new MyCustomDsl();
	}
}

这实际上是 HttpSecurity.authorizeRequests() 等方法的实现方式。

然后你可以使用自定义DSL。

  • Java
@Configuration
@EnableWebSecurity
public class Config {
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.with(MyCustomDsl.customDsl(), (dsl) -> dsl
				.flag(true)
			)
			// ...
		return http.build();
	}
}

该代码按以下顺序调用。

  • Config.configure 方法中的代码被调用
  • MyCustomDsl.init 方法中的代码被调用
  • MyCustomDsl.configure 方法中的代码被调用

如果你愿意,你可以通过使用 SpringFactories 让 HttpSecurity 默认添加 MyCustomDsl。例如,你可以在classpath上创建一个名为 META-INF/spring.factories 的资源,内容如下。

META-INF/spring.factories

org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyCustomDsl

你也可以明确地禁用默认值。

  • Java
@Configuration
@EnableWebSecurity
public class Config {
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.with(MyCustomDsl.customDsl(), (dsl) -> dsl
				.disable()
			)
			...;
		return http.build();
	}
}

五、后处理配置对象

Spring Security的Java配置并没有公开它所配置的每个对象的每个属性。这为大多数用户简化了配置。毕竟,如果每个属性都暴露出来,用户可以使用标准的bean配置。

虽然有很好的理由不直接暴露每个属性,但用户可能仍然需要更高级的配置选项。为了解决这个问题,Spring Security引入了 ObjectPostProcessor 的概念,它可以用来修改或替换许多由Java配置创建的 Object 实例。例如,为了配置 FilterSecurityInterceptor 上的 filterSecurityPublishAuthorizationSuccess 属性,你可以使用下面的方法。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
	http
		.authorizeRequests(authorize -> authorize
			.anyRequest().authenticated()
			.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
				public <O extends FilterSecurityInterceptor> O postProcess(
						O fsi) {
					fsi.setPublishAuthorizationSuccess(true);
					return fsi;
				}
			})
		);
	return http.build();
}


http://www.kler.cn/a/107774.html

相关文章:

  • 知识库管理系统:企业数字化转型的加速器
  • 物理设备命名规则(Linux网络服务器 15)
  • activiti5基础和springboot整合
  • zabbix监控端界面时间与服务器时间不对应
  • redhat虚拟机
  • 7天用Go从零实现分布式缓存GeeCache(学习)(3)
  • 命令行参数、环境变量
  • 集合总结(Java)
  • JavaScript_Pig Game切换当前玩家
  • 【Linux】权限完结
  • 从lc560“和为 K 的子数组“带你认识“前缀和+哈希表“的解题思路
  • 【iPad已停用】解锁教程
  • 现代挖掘机vr在线互动展示厅是实现业务增长的加速度
  • Java集合-HashMap源码分析
  • Docker多平台、跨平台编译打包
  • 【ChatGPT系列】ChatGPT:创新工具还是失业威胁?
  • spark3.3.x处理excel数据
  • 【Python机器学习】零基础掌握RandomForestClassifier集成学习
  • 小程序原生开发中的onLoad和onShow
  • Games104现代游戏引擎笔记 网络游戏进阶架构
  • Spring定时任务+webSocket实现定时给指定用户发送消息
  • SpringBoot内置工具类之断言Assert的使用与部分解析
  • CVPR2023新作:基于组合空时位移的视频修复
  • Tensorflow2 中模型训练标签顺序和预测结果标签顺序不一致问题解决办法
  • Jmeter调用Python脚本实现参数互相传递的实现
  • leetcode做题笔记204. 计数质数