Spring 为什么PermissionEvaluator中的Serializable targetId在某些情况下为null,而在其他情况下不为null?

Spring 为什么PermissionEvaluator中的Serializable targetId在某些情况下为null,而在其他情况下不为null?,spring,spring-security,Spring,Spring Security,我们正在实现PermissionEvaluator,如下所示,它抛出一个NullPointerException(注释为“NPE HERE”): 查看后,targetId似乎为null。但是,此代码的原始作者能够毫无问题地运行此代码。我试图对我们的回购协议进行区分,但没有发现任何有意义的东西。我也搜索了SO和google,但没有找到多少信息 可序列化的targetId保存在哪里?为什么它在某些情况下是空的,而在其他情况下不是空的 考虑到这可能是我实现UserDetails的方式,下面是相关的部分

我们正在实现
PermissionEvaluator
,如下所示,它抛出一个
NullPointerException
(注释为“NPE HERE”):

查看后,targetId似乎为null。但是,此代码的原始作者能够毫无问题地运行此代码。我试图对我们的回购协议进行区分,但没有发现任何有意义的东西。我也搜索了SO和google,但没有找到多少信息

可序列化的targetId保存在哪里?为什么它在某些情况下是空的,而在其他情况下不是空的

考虑到这可能是我实现UserDetails的方式,下面是相关的部分。它们是基于惠勒和怀特在春季实践中的实现

我正在实施以下UserDetails:

public class UserDetailsAdapter implements UserDetails {

    public UserDetailsAdapter(Account account) {
       this.account = account;
    }

    public Account getAccount() {
       return account;
    }

    public Integer getId() {
       return account.getId();
    }

    public String getFirstName() {
       return account.getFirstName();
    }

    public String getLastName() {
       return account.getLastName();
    }

    public String getEmail() {
       return account.getEmail();
    }

    @Override
    public String getUsername() {
       return account.getEmail();
    }

    @Override
    public String getPassword() {
       return account.getPassword();
    }

    @Override
    public boolean isAccountNonExpired() {
       return true;
    }

    @Override
    public boolean isAccountNonLocked() {
       return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
       return true;
    }

    @Override
    public boolean isEnabled() {
       return account.isEnabled();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
       Set<GrantedAuthority> authorities = new HashSet<>();
       for (Role role : account.getRoles()) {
         authorities.add(new SimpleGrantedAuthority(role.getName()));
       }
       return authorities;
    }

    private Account account;

    private static final long serialVersionUID = 2251948358105443813L;

    @Override
    public String toString() {
        return "UserDetailsAdapter [account=" + account + ", firstName=" +
        account.getFirstName() + ", lastName=" + account.getLastName() + "]";
    }

}
在@Controller中:

@RequestMapping(value = {"/company"}, method = RequestMethod.GET)
public String createForm(Model model) {
    model.addAttribute("company", companyService.createCompany());
    return "company";
}
在@服务中:

public Company createCompany() {
     return companyDao.create();
}

我看到它一直存在于数据库中,并分配了一个ID

我们的开发人员能够通过在编译时将调试信息添加到构建中(在我们的例子中,是一个ant
build.xml
)来纠正这个问题

例如,在调试级别中包括“vars”:

  <target name="compile" depends="init"
          description="compile the source">
    <javac srcdir="${src}" destdir="${build}" source="1.7" target="1.7"
       nowarn="true" debug="true" debuglevel="lines,source,vars"
       includeantruntime="true" deprecation="${deprecation}">
      <compilerarg value="-Xbootclasspath/p:${toString:pathing.classpath}"/>
    </javac>
    <javac srcdir="${project_dir}/src/test" destdir="${build}" source="1.7" target="1.7"
       nowarn="true" debug="true" debuglevel="lines,source,vars"
       includeantruntime="true" deprecation="${deprecation}">
      <compilerarg value="-Xbootclasspath/p:${toString:pathing.classpath}"/>
    </javac>
  </target>


我认为Maven
pom.xml的解决方案类似于Maven
pom.xml

,我猜当您有一个新创建的对象尚未保存时(即,id是在保存后生成的)。感谢您的评论,@RobWinch,特别是来自Spring作者的评论。我会看一看。我试图保存对象,但没有成功。在pom.xml中,这意味着添加到maven编译器插件:
true行、vars、source
<authentication-manager >
   <authentication-provider user-service-ref="myUserDetailsService">
    <password-encoder ref="passwordEncoder" />
   </authentication-provider>
</authentication-manager>

<beans:bean id="myUserDetailsService"
         class="com.company.service.UserDetailsServiceImpl" />

<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

<global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
    <expression-handler ref="expressionHandler"/>
</global-method-security>

<beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <beans:property name="permissionEvaluator">
        <beans:bean id="permissionEvaluator" class="com.company.web.security.MethodsPermissionEvaluator"/>
    </beans:property>
</beans:bean>
@Override
public Company create() {
   Company company = new Company();
   company.setCreationDate(new Date());
   save(company);
   return company;
}
@RequestMapping(value = {"/company"}, method = RequestMethod.GET)
public String createForm(Model model) {
    model.addAttribute("company", companyService.createCompany());
    return "company";
}
public Company createCompany() {
     return companyDao.create();
}
  <target name="compile" depends="init"
          description="compile the source">
    <javac srcdir="${src}" destdir="${build}" source="1.7" target="1.7"
       nowarn="true" debug="true" debuglevel="lines,source,vars"
       includeantruntime="true" deprecation="${deprecation}">
      <compilerarg value="-Xbootclasspath/p:${toString:pathing.classpath}"/>
    </javac>
    <javac srcdir="${project_dir}/src/test" destdir="${build}" source="1.7" target="1.7"
       nowarn="true" debug="true" debuglevel="lines,source,vars"
       includeantruntime="true" deprecation="${deprecation}">
      <compilerarg value="-Xbootclasspath/p:${toString:pathing.classpath}"/>
    </javac>
  </target>