添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Spring Security 5.7.0-M2 废弃了 WebSecurityConfigurerAdapter ,根据官方的说法,是希望用户使用基础组件来构建安全配置

在下面的例子中,我们按照官方提供的最佳实践方法使用 Spring Security lambda DSL HttpSecurity#authorizeHttpRequests 方法来定义我们的授权规则

如果你对 Spring Security lambda DSL 有兴趣,可以阅读这篇文章: 文章地址

如果你想要知道为什么要选择 HttpSecurity#authorizeHttpRequests ,可以阅读这篇文章: 文章地址

1. Configuring HttpSecurity

5.4 版本中我们使用 HttpSecurity 来创建一个 SecurityFilterChain Bean

下面是一个使用 WebSecurityConfigurerAdapter 配置示例

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

接下来,在新版本中,官方推荐的写法是:

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

2. Configuring WebSecurity

Spring Security 5.4 版本中,使用WebSecurityCustomizer 于自定义 WebSecurity 的回调接口

下面是一个使用WebSecurityConfigurerAdapter忽略匹配/ignore1/ignore2的配置示例:

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

在新版本中,推荐注入 WebSecurityCustomizer Bean:

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

提示:如果你使用 WebSecurity 来忽略请求,考虑使用permitAll通过HttpSecurity#authorizeHttpRequests 来代替

3. LDAP Authentication

Spring Security 5.7 中,可以使用 EmbeddedLdapServerContextSourceFactoryBeanLdapBindAuthenticationManagerFactoryLdapPasswordComparisonAuthenticationManagerFactory 来创建嵌入式LDAP服务器和执行LDAP身份验证的AuthenticationManager

下面是一个使用WebSecurityConfigurerAdapter的配置示例,它创建了一个嵌入式LDAP服务器和一个AuthenticationManager, AuthenticationManager使用绑定身份验证执行LDAP身份验证:

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

接下来,官方推荐的方法是使用新的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();

4. JDBC Authentication

下面是一个使用WebSecurityConfigurerAdapter的配置示例,带有一个内嵌的数据源,用默认模式初始化并且只有一个用户:

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

在新版本中,更推荐注册一个 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;

注意:在这个例子里,我们使用 User.withDefaultPasswordEncoder() 方法来提高可读性,并不推荐在生产环境中使用,比如你可以使用自定义的哈希密码

5. In-Memory Authentication

下面是一个使用WebSecurityConfigurerAdapter内存中用户的示例配置:

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

新版本中,更推荐通过注册 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);

注意:在这个例子里,我们使用 User.withDefaultPasswordEncoder() 方法来提高可读性,并不推荐在生产环境中使用,比如你可以使用自定义的哈希密码

6. Global AuthenticationManager

只需将AuthenticationManager注册为Bean

可以参考: LDAP Authentication

7. Local AuthenticationManager

Spring Security 5.6 版本中,我们使用 httpsecurity# authenticationManager 方法,覆盖SecurityFilterChain默认的authenticationManager:

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

9. Accessing the local AuthenticationManager

可以在自定义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();

然后,在构建SecurityFilterChain时可以应用自定义DSL:

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

翻译来源文章:https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter

浏览量: 1,971