Spring Boot 1.4:Principal 不能为 null 异常

Posted

技术标签:

【中文标题】Spring Boot 1.4:Principal 不能为 null 异常【英文标题】:Spring Boot 1.4: Principal must not be null exception 【发布时间】:2016-12-21 19:57:08 【问题描述】:

自 Spring boot 1.4 发布以来,我遇到了以下问题 我有一个自定义身份验证提供程序,用于管理 Spring Security 的 JWT 令牌解析。基本上,当令牌无效或过期时,我会抛出 BadCredentialsException。我还有一个 AutenticationEntryPoint,它使用 JSON 中未经授权的 HttpServlet 响应重新格式化消息

@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException

    httpServletResponse.setContentType("application/json");
    httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    httpServletResponse.getOutputStream().println(" \"error\": \"" + e.getMessage() + "\" ");


这里是管理 Authentication Provider 异常的过滤器

@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException



    String authToken = httpServletRequest.getHeader("Authorization");



    JwtToken token = new JwtToken(authToken);
    try
    
        Authentication auth = authenticationManager.authenticate(token);
        SecurityContextHolder.getContext().setAuthentication(auth);
        filterChain.doFilter(httpServletRequest, httpServletResponse);

    
    catch(AuthenticationException ae)
    
        SecurityContextHolder.clearContext();
        unauthorizedHandler.commence(httpServletRequest, httpServletResponse, ae);
    

这在 Spring Boot 1.3.6 中运行良好 现在我收到以下错误

java.lang.IllegalArgumentException:主体不能为空 堆栈跟踪:

java.lang.IllegalArgumentException: Principal must not be null
at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.boot.actuate.audit.AuditEvent.<init>(AuditEvent.java:83) ~[spring-boot-actuator-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.actuate.audit.AuditEvent.<init>(AuditEvent.java:59) ~[spring-boot-actuator-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.actuate.security.AuthenticationAuditListener.onAuthenticationFailureEvent(AuthenticationAuditListener.java:67) ~[spring-boot-actuator-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.actuate.security.AuthenticationAuditListener.onApplicationEvent(AuthenticationAuditListener.java:50) ~[spring-boot-actuator-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.actuate.security.AuthenticationAuditListener.onApplicationEvent(AuthenticationAuditListener.java:34) ~[spring-boot-actuator-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:166) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:382) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:336) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.security.authentication.DefaultAuthenticationEventPublisher.publishAuthenticationFailure(DefaultAuthenticationEventPublisher.java:124) ~[spring-security-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.authentication.ProviderManager.prepareException(ProviderManager.java:240) ~[spring-security-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:233) ~[spring-security-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:454) ~[spring-security-config-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at com.icentia.tracking.security.JwtFilter.doFilterInternal(JwtFilter.java:49) ~[classes/:na]

这来自 Spring Boot Actuator。如果我删除它,它会像以前一样工作吗?!?

这里似乎列出了一个错误,虽然不一样: https://github.com/spring-projects/spring-boot/issues/6447

我想在生产中使用 Actuator,我可以使用任何解决方法吗?

谢谢

【问题讨论】:

嗨 - 很久没发这个了,你解决了这个问题吗? 问题是一旦添加到 Spring Boot 中,Acutator 会跟踪不成功的登录(审核)。我将 JWT 检查从抛出 BadCredential 异常更改为 Nonce 异常,这成功了,可能是因为在这种情况下它没有检查 Principal 的 getName (但我没有验证这一点) 很高兴知道,谢谢! Esteban 也发布了类似的答案。 【参考方案1】:

确保Principal 接口中的getName() 方法在JwtToken 类中返回非空值。

【讨论】:

阿里,请注意 - 该问题可能与引用的开放式 Spring Boot 错误无关,因为您有一个有效的身份验证链。 spring boot 的问题是,即使你手动注册了@WebSecurityConfiguration,默认的bean仍然被安装

以上是关于Spring Boot 1.4:Principal 不能为 null 异常的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 1.4 中自定义 Jackson

Spring Security OAuth2 JWT 资源服务器(旧版)具有 NULL Principal

在 Spring Boot 1.4 中测试 Spring MVC 切片的问题

Spring boot 1.4 测试:配置错误:发现@BootstrapWith 的多个声明

spring cloud 版本 Brixton.SR5 with spring boot 1.4

Spring Boot 1.4 - REST API 测试