当前位置: 代码迷 >> 综合 >> SpringSecurity------引入方式和配置(一)
  详细解决方案

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

热度:49   发布时间:2023-12-20 23:15:48.0

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

    • 1、使用Spring Boot构建
    • 2、不使用Spring Boot构建
    • 3、Maven 仓库
    • 4、Spring MVC使用Spring Security的Java Configuration配置步骤
      • 4.1 、配置UserDetailsService
      • 4.2、注册SecurityFilterChain、引入WebSecurityConfig配置文件
      • 4.3、配置SecurityFilterChain
      • 4.4、配置多个SecurityFilterChain
      • 4.5、自定义DSLs
      • 4.6、Post Processing Configured Objects

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 {
    @Beanpublic 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 SecurityWebApplicationInitializerextends AbstractSecurityWebApplicationInitializer {
    //开启 HttpSessionEventPublisher@Overrideprotected boolean enableHttpSessionEventPublisher() {
    return true;}// ... other overrides ...
}
public class MvcWebApplicationInitializer extendsAbstractAnnotationConfigDispatcherServletInitializer {
    @Overrideprotected 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 {
    //创建一个用户名密码加载器@Beanpublic 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指定排序的拦截器默认是最后执行@Beanpublic 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;@Overridepublic void init(HttpSecurity http) throws Exception {
    //添加任何其他配置器都需要在这个init方法中http.csrf().disable();}@Overridepublic 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 {
    @Beanpublic 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 {
    @Beanpublic 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------密码存储(二)

  相关解决方案