Spring Security—配置(Configuration)

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中拥有多个 节点一样。关键是要注册多个 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();
}

更多项目资讯获取:

大家点赞、收藏、关注、评论啦 、查看👇🏻👇🏻👇🏻获取项目下载链接,博主联系方式👇🏻👇🏻👇🏻

链接点击直达:下载链接

  • 26
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值