空指针异常。 Spring 安全过滤器失败

Posted

技术标签:

【中文标题】空指针异常。 Spring 安全过滤器失败【英文标题】:NullPointerException. Spring security filter failed 【发布时间】:2020-06-01 16:52:31 【问题描述】:

我不知道为什么这个应用程序没有开始显示这个错误。我尝试使用 Spring Security 和 JWT。

2020-Feb-17 12:29:07 PM [main] INFO  org.springframework.aop.framework.CglibAopProxy - Unable to proxy interface-implementing method [public final void org.springframework.web.filter.OncePerRequestFilter.doFilter(javax.servlet.ServletRequest,javax.servlet.ServletResponse,javax.servlet.FilterChain) throws javax.servlet.ServletException,java.io.IOException] because it is marked as final: Consider using interface-based JDK proxies instead!
2020-Feb-17 12:29:07 PM [main] INFO  org.springframework.aop.framework.CglibAopProxy - Unable to proxy interface-implementing method [public final void org.springframework.web.filter.GenericFilterBean.init(javax.servlet.FilterConfig) throws javax.servlet.ServletException] because it is marked as final: Consider using interface-based JDK proxies instead!
2020-Feb-17 12:29:07 PM [main] ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] - Exception starting filter [jwtRequestFilter]
java.lang.NullPointerException: null
    at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:241) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:270) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:106) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4533) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5172) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) [?:?]
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841) [tomcat-embed-core-9.0.29.jar:9.0.29]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [tomcat-embed-core-9.0.29.jar:9.0.29]

这是过滤器代码。我不明白它有什么问题。应用程序刚刚在加载时崩溃,出现与安全过滤器相关的空指针异常。

@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException 

        final String requestTokenHeader = request.getHeader("Authorization");
        String email = null;
        String jwtToken = null;

        if (requestTokenHeader != null && requestTokenHeader.startsWith("FC ")) 
            jwtToken = requestTokenHeader.replace("FC ", "");
            try 
                email = jwtTokenUtil.getEmailFromToken(jwtToken);
             catch (IllegalArgumentException e) 
                System.out.println("Unable to get JWT Token");
             catch (ExpiredJwtException e) 
                System.out.println("JWT Token has expired");
            
         else 
            logger.warn("JWT Token does not begin with FC String");
        

        if (email != null && SecurityContextHolder.getContext().getAuthentication() == null) 
            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(email);
            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) 
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            
        
        chain.doFilter(request, response);
    

@更新

添加过滤器的方法。

@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception 
        httpSecurity.csrf().disable()
                .authorizeRequests().antMatchers("/service/**").permitAll()
                .anyRequest().authenticated().and()
                .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    

【问题讨论】:

查看这个答案:***.com/a/31402509/12576990 如何添加过滤器? NatFar,我添加了过滤器。 也许这与您的问题无关,但我想知道您为什么要尝试通过解析 JWT 令牌手动验证用户身份?由于您使用的是 Spring Security 5.2.2.RELEASE,所有这些工作都已经为您完成了。您唯一需要做的就是指明授权服务器 uri:docs.spring.io/spring-security/site/docs/current/reference/… 并根据需要调整角色:docs.spring.io/spring-security/site/docs/current/reference/… akuma8,我没有授权服务器,所以我自己验证令牌。 【参考方案1】:

我遇到了完全相同的问题,这是我的应用程序中的 spring aop 配置。我添加了一个切入点来排除 GenricFilterBean 类的实现,一切似乎都正常。

【讨论】:

【参考方案2】:

这里的比赛有点晚了,但我也遇到了同样的例外。线索是空指针上方的 INFO 中的 CGLIB 代理和通用过滤器异常。你在这里有@Transactional 吗?您是否围绕这些方法定义了任何事务功能?我的 doFilterInternal 上有 @Transactional。删除 @Transactional 解决了我的问题。

【讨论】:

【参考方案3】:

我遇到了同样的问题,我是这样解决的:

1- 创建自定义注解:

@Target(ElementType.METHOD)
public @interface NoLogging


2-注释doFilterInternal

    @Override
    @NoLogging
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

3- 从 AOP 中排除使用此注解注解的方法:

@Before(value = "execution(* com.company..*..*(..)) && !@annotation(com.company.aop.NoLogging)")
    public void logEntry(JoinPoint joinPoint)

【讨论】:

以上是关于空指针异常。 Spring 安全过滤器失败的主要内容,如果未能解决你的问题,请参考以下文章

ArtifactoryPublish 因空指针异常而失败

SpringBug记录 -- java.lang.NullPointerException在Spring单元测试中遇到的空指针异常及依赖注入异常总结

Spring自动装配空指针异常[重复]

Spring Security 3.1 + JPA - 空指针异常

Keycloak Spring 多租户空指针异常

Spark 2.2 空安全左外连接空指针异常