龙空技术网

Spring Security—配置(Configuration)

DOKER数码 133

前言:

眼前各位老铁们对“spring security配置详解”大概比较注意,姐妹们都想要了解一些“spring security配置详解”的相关资讯。那么小编在网络上搜集了一些关于“spring security配置详解””的相关文章,希望大家能喜欢,我们快快来了解一下吧!

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配置的使用。

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@EnableWebSecuritypublic 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()AbstractSecurityWebApplicationInitializer

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

不使用 Spring 的 AbstractSecurityWebApplicationInitializer - 如果你还没有使用Spring,请使用这些说明。使用 SpringMCV 的 AbstractSecurityWebApplicationInitializer - 如果你已经在使用Spring,请使用这些说明。不使用 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。使用 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 )在幕后被调用。它被配置为以下的默认实现。

@Beanpublic 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@EnableWebSecuritypublic 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@EnableWebSecuritypublic 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@EnableWebSecuritypublic 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 属性,你可以使用下面的方法。

@Beanpublic 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();}

标签: #spring security配置详解