org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.处出现 NullPointerException

发布于 2025-01-11 06:22:48 字数 5345 浏览 0 评论 0原文

关于测试 WebSecurityConfigurerAdapterconfigure 方法的小问题。

我正在使用 Spring Boot 2.6.3,因此 spring-boot-starter-security 2.6.3 (适用于 Spring 2.x.x+ 的问题)

我有自己的安全配置,如下所示:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;

@Configuration
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        final var httpSecurity = http.authorizeRequests()
                .antMatchers("/health")
                .permitAll()
                .and()
                .httpBasic()
                .and()
                .csrf()
                .ignoringAntMatchers("/instances")
                .and()
                .authorizeRequests();
        httpSecurity.anyRequest()
                .authenticated()
                .and()
                .x509()
                .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                .userDetailsService(username -> new User(username, "password", AuthorityUtils.commaSeparatedStringToAuthorityList(username)))
                .and()
                .saml2Login()
                .relyingPartyRegistrationRepository(new InMemoryRelyingPartyRegistrationRepository());
    }

}

我只想编写适当的测试,例如测试路线,如 /health /badhealth /instances /foo 等。

为了做到这一点,我编写我的单元测试如下:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import java.util.HashMap;

class MySecurityConfigurationTest {

    @DisplayName("Test ALL")
    @Test
    void testConfigure() {
        MySecurityConfiguration mySecurityConfiguration1 = new MySecurityConfiguration();
        try {
            mySecurityConfiguration1.configure(new HttpSecurity(new ObjectPostProcessor<>() {
                @Override
                public <O> O postProcess(O object) {
                    return null;
                }
            }, new AuthenticationManagerBuilder(new ObjectPostProcessor<>() {
                @Override
                public <O> O postProcess(O object) {
                    return null;
                }
            }), new HashMap<>()));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

不幸的是,我总是得到一个 NPE,甚至在有机会测试之前路线。

java.lang.NullPointerException
    at org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.<init>(ExpressionUrlAuthorizationConfigurer.java:109)
    at org.springframework.security.config.annotation.web.builders.HttpSecurity.authorizeRequests(HttpSecurity.java:1183)
    at [...]
org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

我很难理解这个 NPE 的原因、什么是 null 以及如何正确测试它。

我应该特别设置一些我错过的东西吗?也许是我没有利用的一些模拟?

最后,有没有一种方法可以静态测试这一点,而无需启动服务器本身?

谢谢

Small question on testing the configure method of WebSecurityConfigurerAdapter please.

I am using Spring Boot 2.6.3, and therefore spring-boot-starter-security 2.6.3 (question applicable to Spring 2.x.x+)

I have my own security configuration written as follow:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;

@Configuration
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        final var httpSecurity = http.authorizeRequests()
                .antMatchers("/health")
                .permitAll()
                .and()
                .httpBasic()
                .and()
                .csrf()
                .ignoringAntMatchers("/instances")
                .and()
                .authorizeRequests();
        httpSecurity.anyRequest()
                .authenticated()
                .and()
                .x509()
                .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                .userDetailsService(username -> new User(username, "password", AuthorityUtils.commaSeparatedStringToAuthorityList(username)))
                .and()
                .saml2Login()
                .relyingPartyRegistrationRepository(new InMemoryRelyingPartyRegistrationRepository());
    }

}

I just want to write appropriate tests, such as testing the routes, like /health /badhealth /intances /foo, etc.

In order to do so, I am writing my unit test as follow:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import java.util.HashMap;

class MySecurityConfigurationTest {

    @DisplayName("Test ALL")
    @Test
    void testConfigure() {
        MySecurityConfiguration mySecurityConfiguration1 = new MySecurityConfiguration();
        try {
            mySecurityConfiguration1.configure(new HttpSecurity(new ObjectPostProcessor<>() {
                @Override
                public <O> O postProcess(O object) {
                    return null;
                }
            }, new AuthenticationManagerBuilder(new ObjectPostProcessor<>() {
                @Override
                public <O> O postProcess(O object) {
                    return null;
                }
            }), new HashMap<>()));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

Unfortunately, I am always getting a NPE, before even having the chance to test the routes.

java.lang.NullPointerException
    at org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.<init>(ExpressionUrlAuthorizationConfigurer.java:109)
    at org.springframework.security.config.annotation.web.builders.HttpSecurity.authorizeRequests(HttpSecurity.java:1183)
    at [...]
org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

I am having a hard time understand the reason of this NPE, what is null, and how to properly test this.

Should I set something up in particular that I missed? Maybe some Mock that I am not leveraging?

Finally, is there a way to test this statically, without having to spin up the server itself?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我恋#小黄人 2025-01-18 06:22:48

旧的(例如 spring-security-config-5.5.5)ExpressionUrlAuthorizationConfigurer 构造函数看起来像这样,

public ExpressionUrlAuthorizationConfigurer(ApplicationContext context) {
    this.REGISTRY = new ExpressionInterceptUrlRegistry(context);
}

新的(spring-security-config-5.6.2)现在有 context.getBeanNamesForType (...

public ExpressionUrlAuthorizationConfigurer(ApplicationContext context) {
    String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
    if (grantedAuthorityDefaultsBeanNames.length == 1) {
        GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(grantedAuthorityDefaultsBeanNames[0],
                GrantedAuthorityDefaults.class);
        this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
    }
    else {
        this.rolePrefix = "ROLE_";
    }
    this.REGISTRY = new ExpressionInterceptUrlRegistry(context);
}

由于应用程序上下文尚未启动,context 为 null,并且您得到 NPE。以前,测试没有ApplicationContext,现在可以了。
我相信您必须启动上下文才能通过测试:https://spring. io/guides/gs/testing-web/

The old (spring-security-config-5.5.5, for example) ExpressionUrlAuthorizationConfigurer constructor looked like this

public ExpressionUrlAuthorizationConfigurer(ApplicationContext context) {
    this.REGISTRY = new ExpressionInterceptUrlRegistry(context);
}

the new one (spring-security-config-5.6.2) now has context.getBeanNamesForType(...

public ExpressionUrlAuthorizationConfigurer(ApplicationContext context) {
    String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
    if (grantedAuthorityDefaultsBeanNames.length == 1) {
        GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(grantedAuthorityDefaultsBeanNames[0],
                GrantedAuthorityDefaults.class);
        this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
    }
    else {
        this.rolePrefix = "ROLE_";
    }
    this.REGISTRY = new ExpressionInterceptUrlRegistry(context);
}

Since the application context hasn't been started, context is null and you get the NPE. Before, it didn't matter that the test didn't have an ApplicationContext, now it does.
I believe you will have to initiate the context for the tests to pass: https://spring.io/guides/gs/testing-web/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文