java - Spring security - 错误导致性能问题

标签 java spring spring-boot spring-security

我遇到了 SpringBoot 应用程序的问题。我的 ICS 报告此 API 的响应时间较长但我的代码指标显示一切正常,例如,发送到我的 API 的查询只需要 50 毫秒即可运行“业务” ”代码但有效响应需要超过500ms!

我的 JVM 的内部日志显示,在每个请求中,即使凭据正确并且 API 工作正常,我也会收到“UsernameNotFoundExcption”。这就是为什么我认为我的问题来自 SpringSecurity 层,但我无法确定原因。

我的切入点:

@Component
public class BasicAuthenticationPoint extends BasicAuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
            throws IOException, ServletException {
        response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName());
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setCharacterEncoding("utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401 - " + authEx.getMessage());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("MYAPI");
        super.afterPropertiesSet();
    }
}

还有我的适配器:

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private BasicAuthenticationPoint basicAuthenticationPoint;

    @Bean
    public BCryptPasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        HttpSecurity httpSec = http.csrf().disable();
        httpSec = httpSec.authorizeRequests()
                .antMatchers("/my-business-resources/**").hasRole("USER")
                .antMatchers("/actuator/**").hasRole("ADMIN")
                .and();
        httpSec.httpBasic().authenticationEntryPoint(basicAuthenticationPoint).and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // Load users file
        Resource confFile = resourceLoader.getResource("classpath:users.list");
        
        // Returns users from the configuration file <username, password (BCrypted), admin (boolean)>
        List<ApiUser> users = ApiUtils.getUsersFromFile(confFile);
        
        for(ApiUser u : users){
            // Add the username/password to the in-memory authentication manager
            if (u.admin)
                auth.inMemoryAuthentication().withUser(u.username).password(u.password).roles("USER", "ADMIN");
            else
                auth.inMemoryAuthentication().withUser(u.username).password(u.password).roles("USER");

        }
    }
}

我错过了什么吗?

PS:我的 Spring Boot 应用程序打包为 WAR 并在 Tomcat 服务器内执行以实现标准化。

编辑:

这是完整的 UsernameNotFound 堆栈跟踪(ICS 格式):

Exception Details
Type:   UsernameNotFoundException
Exception Class:    org.springframework.security.core.userdetails.UsernameNotFoundException
API:    Exception
Thread Name:    https-openssl-apr-9343-exec-10 <522634598>

Exception StackTrace
Method  Class   Line    File Name
loadUserByUsername  org.springframework.security.provisioning.InMemoryUserDetailsManager    146 <unknown>
retrieveUser    org.springframework.security.authentication.dao.DaoAuthenticationProvider   104 <unknown>
authenticate    org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider   144 <unknown>
authenticate    org.springframework.security.authentication.ProviderManager 174 <unknown>
authenticate    org.springframework.security.authentication.ProviderManager 199 <unknown>
doFilterInternal    org.springframework.security.web.authentication.www.BasicAuthenticationFilter   180 <unknown>
doFilter    org.springframework.web.filter.OncePerRequestFilter 107 <unknown>
doFilter    org.springframework.security.web.FilterChainProxy$VirtualFilterChain    334 <unknown>
doFilter    org.springframework.security.web.authentication.logout.LogoutFilter 116 <unknown>
doFilter    org.springframework.security.web.FilterChainProxy$VirtualFilterChain    334 <unknown>
doFilterInternal    org.springframework.security.web.header.HeaderWriterFilter  66  <unknown>
doFilter    org.springframework.web.filter.OncePerRequestFilter 107 <unknown>
doFilter    org.springframework.security.web.FilterChainProxy$VirtualFilterChain    334 <unknown>
doFilter    org.springframework.security.web.context.SecurityContextPersistenceFilter   105 <unknown>
doFilter    org.springframework.security.web.FilterChainProxy$VirtualFilterChain    334 <unknown>
doFilterInternal    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter 56  <unknown>
doFilter    org.springframework.web.filter.OncePerRequestFilter 107 <unknown>
doFilter    org.springframework.security.web.FilterChainProxy$VirtualFilterChain    334 <unknown>
doFilterInternal    org.springframework.security.web.FilterChainProxy   215 <unknown>
doFilter    org.springframework.security.web.FilterChainProxy   178 <unknown>
invokeDelegate  org.springframework.web.filter.DelegatingFilterProxy    357 <unknown>
doFilter    org.springframework.web.filter.DelegatingFilterProxy    270 <unknown>
internalDoFilter    org.apache.catalina.core.ApplicationFilterChain 193 <unknown>
doFilter    org.apache.catalina.core.ApplicationFilterChain 166 <unknown>
doFilter    org.springframework.boot.web.servlet.support.ErrorPageFilter    130 <unknown>
access$000  org.springframework.boot.web.servlet.support.ErrorPageFilter    66  <unknown>
doFilterInternal    org.springframework.boot.web.servlet.support.ErrorPageFilter$1  105 <unknown>
doFilter    org.springframework.web.filter.OncePerRequestFilter 107 <unknown>
doFilter    org.springframework.boot.web.servlet.support.ErrorPageFilter    123 <unknown>
internalDoFilter    org.apache.catalina.core.ApplicationFilterChain 193 <unknown>
doFilter    org.apache.catalina.core.ApplicationFilterChain 166 <unknown>
filterAndRecordMetrics  org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter    155 <unknown>
filterAndRecordMetrics  org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter    123 <unknown>
doFilterInternal    org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter    108 <unknown>
doFilter    org.springframework.web.filter.OncePerRequestFilter 107 <unknown>
internalDoFilter    org.apache.catalina.core.ApplicationFilterChain 193 <unknown>
doFilter    org.apache.catalina.core.ApplicationFilterChain 166 <unknown>
doFilterInternal    org.springframework.web.filter.CharacterEncodingFilter  200 <unknown>
doFilter    org.springframework.web.filter.OncePerRequestFilter 107 <unknown>
internalDoFilter    org.apache.catalina.core.ApplicationFilterChain 193 <unknown>

最佳答案

好吧,经过一番调试,我发现了问题所在!

问题出在我用来填充内存 validator 的代码中:

for(ApiUser u : users){
    // Add the username/password to the in-memory authentication manager
    if (u.admin)
        auth.inMemoryAuthentication().withUser(u.username).password(u.password).roles("USER", "ADMIN");
    else
        auth.inMemoryAuthentication().withUser(u.username).password(u.password).roles("USER");
}

调用auth.inMemoryAuthentication()的事实多次创建新的InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>每次( Spring code ),因此我们有尽可能多的不同 AuthenticationManager作为用户(每个用户一个用户),因此每个请求都会多次执行身份验证过程。

以下是我修复该错误的方法:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    // Load users file
    Resource confFile = resourceLoader.getResource("classpath:users.list");

    // Returns users from the configuration file <username, password (BCrypted), admin (boolean)>
    List<ApiUser> users = ApiUtils.getUsersFromFile(confFile);

    @SuppressWarnings("rawtypes")
    UserDetailsBuilder udb = null;

    for(ApiUser u : users){
        // Add the username/password to the in-memory authentication manager
        if (udb == null)
            udb = auth.inMemoryAuthentication().withUser(u.username).password(u.password);
        else
            udb = udb.and().withUser(u.username).password(u.password);

        if (u.admin)
            udb.roles("USER", "ADMIN");
        else
            udb.roles("USER");
    }
}

现在我的平均响应时间是 80ms

关于java - Spring security - 错误导致性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53595574/

相关文章:

java - 多级泛型类型的返回值不能分配给扩展类型

java - 如何在我的 React JHipster 应用程序中添加 fontawesome 图标?

Spring webflux,测试 `ServerResponse`

java - 如何在 Spring Boot JUnit 测试中排除 *AutoConfiguration 类?

spring-boot - Spring Boot 分页返回的值不一致

java - 使用 Spring Boot Java 嵌入 Grizzly (glassfish) Servlet 容器

java - 在Java中运行 'openssl req'命令?

Java:DBunitils + Spring:不同的 Hibernate 方言

spring-boot - 任务 :compileKotlin FAILED. 未解析的引用 : web, 未解析的引用:GetMapping

java - JPA Repository 变量的方法无法从 SpringBoot Main 方法保存