当前位置:主页 > java教程 > Spring Security配置

Spring Security配置保姆级教程

发布:2023-04-02 08:05:01 59


给大家整理一篇相关的编程文章,网友阚夜春根据主题投稿了本篇教程内容,涉及到Spring、Security配置、Spring、Security、Spring Security配置相关内容,已被764网友关注,如果对知识点想更进一步了解可以在下方电子资料中获取。

Spring Security配置

背景

笔者使用 Spring Security 5.8 时,发现网上很多教程所教的 Spring Security 配置类 SecurityConfig.java 的配置风格还是停留在继承 WebSecurityConfigurerAdapter 的风格。然而, WebSecurityConfigurerAdapter 在 Spring Security 5.7.0-M2 版本中已经被 deprecated 了。因此在本文中分享 Spring 官方最新推荐的 Spring Security 配置风格。

一、前言

在 Spring Security 5.7.0 (2022 年 2 月 21 日更新) 中,官方弃用了 WebSecurityConfigurerAdapter 。因为Spring 官方鼓励开发者朝着组件化安全配置迁移。为了帮助开发者顺利过渡到这种配置风格,Spring 官方准备了一系列常见的使用案例和建议的替代方案。

在下面的例子中,我们将遵循最佳实践,使用 Spring Security lambda DSL 和 HttpSecurity.java 中的 authorizeHttpRequests() 方法来定义授权规则。如果您对 lambda DSL 感到陌生,可以参考我的这篇文章进行学习:《如何使用Lambda DSL配置Spring Security》。

二、配置HttpSecurity

在 Spring Security 5.4 中,新增了通过创建一个 SecurityFilterChain 的 Bean 来配置 HttpSecurity 的功能。

首先来看看没有弃用 WebSecurityConfigurerAdapter 的示例,下面是使用 WebSecurityConfigurerAdapter 的配置示例,该配置使用 httpBasic() 方法来保护所有的接口。

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
    }
}

但今后, WebSecurityConfigurerAdapter 就被 Spring 官方弃用了,取而代之的是通过注册一个 SecurityFilterChain 的 Bean 来配置 HttpSecurity

@Configuration
public class SecurityConfiguration {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
        return http.build();
    }
}

三、配置WebSecurity

在 Spring Security 5.4 中,Spring 官方新增了 WebSecurityCustomizer

WebSecurityCustomizer 是一个回调接口,可以用来配置 WebSecurity

首先来看看先前的旧配置风格的代码示例:使用 WebSecurityConfigurerAdapter 来忽略与 /ignore1/ignore2 匹配的请求 (即不拦截这两个请求进行认证授权) 。

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/ignore1", "/ignore2");
    }
}

但今后,Spring 官方不再推荐上面的配置风格,取而代之的是向 Spring 容器中注入一个 WebSecurityCustomizer 的 Bean 。

@Configuration
public class SecurityConfiguration {
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
    	return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
    }
}

注意:如果你想通过配置 WebSecurity 来忽略请求,建议优先考虑通过配置 HttpSecurityauthorizeHttpRequests() 方法,使用 .permitAll() 来实现。

四、配置LDAP认证

LDAP (Light Directory Access Protocol) ,是基于 X.500 标准的轻量级目录访问协议。有兴趣的同学可以自行谷歌搜索学习,LDAP 这种协议常用于授权认证的情景。

在 Spring Security 5.7 中,Spring 官方新增了 EmbeddedLdapServerContextSourceFactoryBeanLdapBindAuthenticationManagerFactoryLdapPasswordComparisonAuthenticationManagerFactory ,用来创建一个嵌入式 LDAP 服务器和一个 AuthenticationManager 对象,来执行 LDAP 认证。

同样的,先来看先前旧的配置风格的示例,继承 WebSecurityConfigurerAdapter ,创建一个嵌入式 LDAP 服务器,创建一个 AuthenticationManager ,使用绑定认证 (Bind Authentication) 来执行 LDAP 认证。

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .ladpAuthentication()
            .userDetailsContextMapper(new PersonContextMapper())
            .userDnPatterns("uid={0}, ou=people")
            .contextSource()
            .port(0);
    }
}

但今后,Spring 官方不再推荐上面的配置风格,取而代之的是使用新的 LDAP 类。

@Configuration
public class SecurityConfiguration {
    @Bean
    public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
        EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean =
            EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
        contextSourceFactoryBean.setPort(0);
        return contextSourceFactoryBean;
    }
    @Bean
    AuthenticationManager ldapAuthenticationManager(
        	BaseLdapPathContextSource contextSource) {
        LdapBindAuthenticationManagerFactory factory = 
            new LdapBindAuthenticationManagerFactory(contextSource);
        factory.setUserDnPatterns("uid={0}, ou=people");
        factory.setUserDetailsContextMapper(new PersonContextMapper());
        return factory.createAuthenticationManager();
    }
}

五、配置JDBC认证

同样的,先来看先前旧的配置风格的示例,继承 WebSecurityConfigurerAdapter ,使用一个以默认方式初始化且具有一个用户的嵌入式 DataSource

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        auth.jdbcAuthentication()
            .withDefaultSchema()
            .dataSource(dataSource())
            .withUser(user);
    }
}

但今后,Spring 官方不再推荐上面的配置风格,取而代之的是向 Spring 容器注入一个 JdbcUserDetailsManager 的 Bean 。

@Configuration
public class SecurityConfiguration {
    @Bean
    public DataSource datasource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
            .build();
    }
    @Bean
    public UserDetailsManager users(DataSource dataSource) {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
        users.createUser(user);
        return users;
    }
}

注意:上面的代码示例第 14 行中,为了密码的可读性才使用方法 User.withDefaultPasswordEncoder() 。在实际的生产环境中并不会使用默认的密码编码器,因为这样存储的密码是明文,十分不安全。这里推荐使用 BCryptPasswordEncoder 作为密码编码器来对密码进行加密成暗文存储。

六、In-Memory Authentication

与上面存储在数据库的不同,In-Memory 是把用户信息存储在内存中。

同样的,先来看先前旧的配置风格的示例,继承 WebSecurityConfigurerAdapter 来配置存储在内存中的一个用户信息。

@Configuration
public class SecurityConfiguration extends WebSecutiryConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        auth.inMemoryAuthentication()
            .withUser(user);
    }
}

但今后,Spring 官方不再推荐上面的配置风格,取而代之的是向 Spring 容器注入一个 InMemoryUserDetailsManager 的 Bean 。

@Configuration
public class SecurityConfiguration {
    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

注意:上面的代码示例第 6 行中,为了密码的可读性才使用方法 User.withDefaultPasswordEncoder() 。在实际的生产环境中并不会使用默认的密码编码器,因为这样存储的密码是明文,十分不安全。这里推荐使用 BCryptPasswordEncoder 作为密码编码器来对密码进行加密成暗文存储。

七、配置全局AuthenticationManager

如果你想要创建整个应用都可以调用的 AuthenticationManager 对象,只需要简单地使用注解 @Bean 来注入 Spring 容器。

配置风格示例与 LDAP 的配置示例相同。

八、配置局部AuthenticationManager

在 Spring Security 5.6 中,Spring 官方在 HttpSecurity 中新增了方法 authenticationManager() ,该方法重写具体的 SecurityFilterChain 的默认 AuthenticationManager

下面是配置自定义局部 AuthenticationManager 的代码示例。

@Configuration
public class SecurityConfiguration {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
               	.anyRequest().authticated())
            .httpBasic(withDefaults())
            .authenticationManager(new CustomAuthenticationManager());
        return http.build();
    }
}

九、调用局部AuthenticationManager

可以使用 custom DSL 来调用局部 AuthenticationManager 。这实际上正是 Spring Security 内部实现诸如 HttpSecurity.authorizeRequests() 方法的方式。

public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
        http.addFilter(new CustomFilter(authenticationManager));
    }
    public static MyCustomDsl customDsl() {
        return new MyCustomDsl();
    }
}

当Spring Security开始构建 SecurityFilterChain 时,custom DSL 就会被自动调用。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    // ...
    http.apply(customDsl());
    return http.build();
}

到此这篇关于Spring Security配置保姆级教程的文章就介绍到这了,更多相关Spring Security配置内容请搜索码农之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持码农之家!


参考资料

相关文章

  • SpringCloud Feign客户端使用流程

    发布:2023-04-18

    在springcloud中,openfeign是取代了feign作为负载均衡组件的,feign最早是netflix提供的,他是一个轻量级的支持RESTful的http服务调用框架,内置了ribbon,而ribbon可以提供负载均衡机制,因此feign可以作为一个负载均衡的远程服务调用框架使用


  • Spring整合ehCache全过程

    发布:2023-04-03

    这篇文章主要介绍了Spring整合ehCache全过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教


  • Spring Boot加密配置文件方法介绍

    发布:2023-04-26

    这篇文章主要介绍了SpringBoot加密配置文件,近期在对开发框架安全策略方面进行升级优化,提供一些通用场景的解决方案,本文针对配置文件加密进行简单的分享


  • 实例分享springmvc配置线程池Executor做多线程并发操作

    发布:2020-03-21

    今天小编就为大家分享一篇关于springmvc配置线程池Executor做多线程并发操作的代码实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧


  • Spring boot Admin使用eureka监控服务知识总结

    发布:2019-06-04

    本篇文章主要介绍了详解Spring boot Admin 使用eureka监控服务,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧


  • SpringBoot项目集成日志的方法步骤

    发布:2019-06-18

    这篇文章主要介绍了SpringBoot项目集成日志的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧


  • SpringBoot和SpringBatch用法详解

    发布:2019-09-15

    Spring Batch 是一个轻量级的、完善的批处理框架,旨在帮助企业建立健壮、高效的批处理应用。这篇文章主要介绍了详解SpringBoot和SpringBatch 使用,需要的朋友可以参考下


  • SpringBoot获取配置文件内容的几种方式总结

    发布:2023-03-27

    大家都知道SpringBoot获取配置文件的方法有很多,下面这篇文章主要给大家介绍了关于SpringBoot获取配置文件内容的几种方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下


网友讨论