为啥自动装配的 bean 为空?

Posted

技术标签:

【中文标题】为啥自动装配的 bean 为空?【英文标题】:Why autowired bean is null?为什么自动装配的 bean 为空? 【发布时间】:2018-04-16 00:22:32 【问题描述】:

目标

如果用户在登录后尝试访问登录页面,则将用户重定向到主页。

方法

在过滤器级别而不是在登录控制器中重定向用户。

系统详情

JSF

春季安全

UrlRewriteFilter

详情

基于这个link我创建了一个类来访问spring security并询问用户是否登录(不是匿名用户):

 public class SecurityContextAccessorImpl implements SecurityContextAccessor 

    @Autowired
    private AuthenticationTrustResolver authenticationTrustResolver;

    public SecurityContextAccessorImpl() 
    

    @Override
    public boolean isCurrentAuthenticationAnonymous() 
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authenticationTrustResolver.isAnonymous(authentication);
    

然后我开发了一个过滤器,它使用以前的类来重定向用户:

@WebFilter
@Component
public class LoginFilter implements Filter 

    @Autowired
    private SecurityContextAccessor securityContextAccessor;

    @Override
    public void destroy() 
        // TODO Auto-generated method stub

    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException 

        if(securityContextAccessor != null)
            if(securityContextAccessor.isCurrentAuthenticationAnonymous())
                String contextPath = ((HttpServletRequest)request).getContextPath();
                ((HttpServletResponse)response).sendRedirect(contextPath + "/ASSDA/home/home");
            
        

        chain.doFilter(request, response);
    

    @Override
    public void init(FilterConfig arg0) throws ServletException 
        // TODO Auto-generated method stub

    

过滤器在spring和urlrewrite之后在web.xml中定义:

<!-- ============== Spring security ============= -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
<!-- ============== UrlRewriteFilter ============= -->
    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>

    </filter>
    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- ============== Login Filter ============= -->
   <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>es.assda.ged.web.controller.security.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/login.xhtml</url-pattern>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

Beans在对应的applicationContext.xml中定义

    <beans:bean id="defaultTargetUrl" class="java.lang.String">
        <beans:constructor-arg value="/ASSDA/home/home" />
    </beans:bean>

    <beans:bean id="authenticationTrustResolver" name="authenticationTrustResolver" class="org.springframework.security.authentication.AuthenticationTrustResolverImpl" />

<bean id="securityContextAccessor" name="securityContextAccessor" class="es.assda.ged.api.security.SecurityContextAccessorImpl" />

当前行为

重定向做得很好并到达了 LoginFilter,但自动连接的 securityContextAccessor 变量没有被初始化。我认为它没有初始化,因为 bean authenticationTrustResolver 为空。

另一方面,如果我在登录控制器中声明自动装配变量 securityContextAccessor,它会被正确注入。

为什么在 LoginFilter 中 securityContextACcessor 为 null 并在登录控制器中正确实例化?

【问题讨论】:

没有注入 bean 可能是因为它不是由 Spring 管理的。这可能是由于 @WebFilter 使您的过滤器由 JEE 容器管理。 【参考方案1】:

看起来你没有通过 Spring 实例化你的 Filter,所以你没有得到依赖注入。它应该使用DelegatingFilterProxy:

web.xml:

<filter>
   <filter-name>springLoginFilter</filter-name><!-- Your filter bean in Spring -->
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
   <filter-name>LoginFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

applicationContext.xml:

<bean id="springLoginFilter" class="es.assda.ged.web.controller.security.LoginFilter" />  

另外,请参阅Accessing Spring beans from servlet filters and tags

【讨论】:

以上是关于为啥自动装配的 bean 为空?的主要内容,如果未能解决你的问题,请参考以下文章

SpringBean自动装配

Spring之Bean的自动装配

Spring随笔-bean装配-自动装配

第2章—装配Bean—自动化装配Bean

Bean 的自动装配

Bean 的自动装配