SpringSecurity------引入方式和配置(一)

本文详细介绍了如何在Spring项目中引入和配置SpringSecurity,包括SpringBoot和非SpringBoot环境下的依赖管理,以及SpringMVC中Java配置的安全设置。内容涵盖UserDetailsService配置,SecurityFilterChain的注册与定制,多FilterChain配置,自定义DSLs以及对象后处理。

1、使用Spring Boot构建

优先考虑使用Spring Initializr或是IDE软件集成的Spring Initializr引入Starter,或者也可以手动添加maven依赖引入:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
	    <version>5.5.0-SNAPSHOT</version>
    </dependency>
</dependencies>

2、不使用Spring Boot构建

当不使用Spring Boot构建Spring Security应用程序,优先考虑使用Spring Security’s BOM,可以保证Spring Security版本号在整个项目中的一致性:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-bom</artifactId>
            <version>{spring-security-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

最小限度使用Spring Security的典型Maven依赖如下:

<dependencies>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
    </dependency>
</dependencies>

很多用户在使用Spring Security时,由于依赖传递的冲突导致奇怪的类路径加载问题,最简单的解决办法是在pom文件中使用spring-framework-bom管理:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>5.3.2-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3、Maven 仓库

所有GA版本(以 .RELEASE结尾的版本) 都部署在Maven Central,所以不需要在POM文件中声明附加的Maven仓库。

如果使用SNAPSHOT版本,需要保证在POM文件中定义了Spring Snapshot仓库地址,如下所示:

<repositories>
    <repository>
        <id>spring-snapshot</id>
        <name>Spring Snapshot Repository</name>
        <url>https://repo.spring.io/snapshot</url>
    </repository>
</repositories>

如果使用Milestone或是Candidate版本,需要保证在POM文件中定义了Spring Milestone仓库地址,如下所示:

<repositories>
    <repository>
        <id>spring-milestone</id>
        <name>Spring Milestone Repository</name>
        <url>https://repo.spring.io/milestone</url>
    </repository>
</repositories>

4、Spring MVC使用Spring Security的Java Configuration配置步骤

4.1 、配置UserDetailsService

使用java配置单一的初始化用户名和密码,以下配置会创建一个Servlet Filter,这个Filter会被注入到SecurityFilterChain,SecurityFilterChain就是处理所有安全认证和鉴权的类,这个简单的配置会为应用程序添加以下安全机制:

  • 所有URL访问都需要鉴权
  • 创建一个登录表单
  • 创建一个用户名为user,密码为password等表单登录账户
  • 允许登出
  • CSRF攻击防护
  • Session维护
  • Security Header集成
    • HTTPS传输协议
    • X-Content-Type-Options
    • Cache Control
    • X-XSS-Protection
    • X-Frame-Options 阻止点击劫持
  • 融入以下可用的Servlet API方法
    • HttpServletRequest#getRemoteUser()

    • HttpServletRequest#getUserPrincipal()

    • HttpServletRequest#isUserInRole(java.lang.String)

    • HttpServletRequest#login(java.lang.String, java.lang.String)

    • HttpServletRequest#logout()

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.*;

@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;
	}
}

也可以在配置文件中指定初始化用户名和密码

spring.security.user.name=user
spring.security.user.password=password

4.2、注册SecurityFilterChain、引入WebSecurityConfig配置文件

AbstractSecurityWebApplicationInitializer用于注册SecurityFilterChain

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

public class SecurityWebApplicationInitializer
	extends AbstractSecurityWebApplicationInitializer {
	//开启 HttpSessionEventPublisher
	@Override
	protected boolean enableHttpSessionEventPublisher() {
		return true;
	}
	// ... other overrides ...
}
public class MvcWebApplicationInitializer extends
		AbstractAnnotationConfigDispatcherServletInitializer {

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

	// ... other overrides ...
}

4.3、配置SecurityFilterChain

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
	http
		.authorizeRequests(authorize -> authorize
			.anyRequest().authenticated()
		)                         //所有请求都需要鉴权
		.formLogin(withDefaults())//表单登录
		.httpBasic(withDefaults());//HTTP Basic登录
	return http.build();
}

4.4、配置多个SecurityFilterChain

@EnableWebSecurity
public class MultiHttpSecurityConfig {
    //创建一个用户名密码加载器
	@Bean
	public UserDetailsService userDetailsService() throws Exception {
		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;
	}
    //注入一个只拦截/api/开头的URL请求的SecurityFilterChain,这个拦截器顺序为1,有限于formLoginFilterChain执行
	@Bean
	@Order(1)
	public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
		http
			.antMatcher("/api/**")
			.authorizeHttpRequests(authorize -> authorize
				.anyRequest().hasRole("ADMIN")
			)
			.httpBasic(withDefaults());
		return http.build();
	}
    //注入另一个处理非/api/开头的URL请求的SecurityFilterChain,没有@Order指定排序的拦截器默认是最后执行
	@Bean
	public SecurityFilterChain formLoginFilterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests(authorize -> authorize
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}

4.5、自定义DSLs

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

	@Override
	public void init(HttpSecurity http) throws Exception {
		//添加任何其他配置器都需要在这个init方法中
		http.csrf().disable();
	}

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

		//这里从ApplicationContext容器中寻找拦截器
		CustomFilter customFilter = context.getBean(CustomFilter .class);
		customFilter .setFlag(flag);
		http.addFilterBefore(customFilter , UsernamePasswordAuthenticationFilter.class);
	}

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

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

注意:HttpSecurity.authorizeRequests()的实现方式和上面的代码类似

通过下面的方式使用自定义的DSLs

@EnableWebSecurity
public class Config {
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.apply(customDsl())
				.flag(true)
				.and()
			...;
		return http.build();
	}
}

可以使用classpath/META-INF/spring.factories文件将自定义的CustomDsl设置为默认加载

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

禁用默认的CustomDsl可以如下配置

@EnableWebSecurity
public class Config {
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.apply(customDsl()).disable()
			...;
		return http.build();
	}
}

4.6、Post Processing Configured Objects

为了简化大多数用户的配置,Spring Security的Java Configuration配置方式并没有公开它所配置的每个对象的每个属性。虽然有很好的理由不直接公开每个属性,但用户可能仍然需要更高级的配置选项。 为了解决这个问题,Spring Security引入了ObjectPostProcessor的概念,它可以用来修改或替换Java Configuration创建的许多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();
}

下一篇:SpringSecurity------密码存储(二)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豢龙先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值