使用 PlainUsername 的空指针异常

Posted

技术标签:

【中文标题】使用 PlainUsername 的空指针异常【英文标题】:Null Pointer Exception using PlainUsername 【发布时间】:2017-01-31 22:29:31 【问题描述】:

当我编辑用户时,所有的人都在保存,但是当我更改密码时,它得到了错误。请帮助我。

 NullPointerException occurred when processing request: [POST] /openbrm   /user/save
 Stacktrace follows:
 java.lang.NullPointerException
at     com.sapienter.jbilling.client.authentication.CompanyUserDetails.getPlainUsername(CompanyUserDetails.java:84)
at  com.sapienter.jbilling.client.authentication.JBillingPasswordEncoder.isPasswordValid(JBillingPasswordEncoder.java:75)
at com.sapienter.jbilling.client.user.UserHelper.bindPassword(UserHelper.groovy:155)
at jbilling.UserController.save(UserController.groovy:304)
at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

UserController.groovy

def save () 
    UserWS user = new UserWS()
    user.mainRoleId= Constants.TYPE_ROOT
    UserHelper.bindUser(user, params)
    def contacts = []

    def userId= params['user']['userId'] as Integer

    log.debug "Save called for user $userId"

    def oldUser = userId ? webServicesSession.getUserWS(userId) : null

    def company_id = session['company_id']
    def company = CompanyDTO.createCriteria().get 
        eq("id", company_id)
        fetchMode('contactFieldTypes', FM.JOIN)
    


    if ( !oldUser || SpringSecurityUtils.ifAllGranted('ROLE_SUPER_USER') || SpringSecurityUtils.ifAllGranted('MY_ACCOUNT_162') ) 
        UserHelper.bindUser(user, params)
        UserHelper.bindContacts(user, contacts, company, params)
     else 
        user= oldUser
        contacts= userId ? webServicesSession.getUserContactsWS(userId) : null
    



    if ( !oldUser || SpringSecurityUtils.ifAllGranted('ROLE_SUPER_USER') || SpringSecurityUtils.ifAllGranted('MY_ACCOUNT_161') ) 
        UserHelper.bindPassword(user, oldUser, params, flash)
     else 
        user.password= null
    
    UserDTO loggedInUser = UserDTO.get(springSecurityService.principal.id)
    if (flash.error) 
        user = new UserWS()
        UserHelper.bindUser(user, params)
        contacts = []
        UserHelper.bindContacts(user, contacts, company, params)
        render view: 'edit', model: [user: user, contacts: contacts, company: company, loggedInUser: loggedInUser, roles: loadRoles()]
        return
    

    try 

        if (!oldUser) 
            log.debug("creating user $user")

            user.userId = webServicesSession.createUser(user)

            flash.message = 'user.created'
            flash.args = [user.userId as String]

         else 
            log.debug("saving changes to user $user.userId")

            webServicesSession.updateUser(user)

            flash.message = 'user.updated'
            flash.args = [user.userId as String]
        

        // save secondary contacts
        if (user.userId) 
            contacts.each 
                webServicesSession.updateUserContact(user.userId, it);
            
        

     catch (SessionInternalError e) 
        flash.clear()
        viewUtils.resolveException(flash, session.locale, e)
        contacts = userId ? webServicesSession.getUserContactsWS(userId) : null
        if(!contacts && !userId)
            contacts = [user.getContact()]
        
        render view: 'edit', model: [user: user, contacts: contacts, company: company, loggedInUser: loggedInUser, roles: loadRoles()]
        return
    

    if ( SpringSecurityUtils.ifAnyGranted("MENU_99") || SpringSecurityUtils.ifAnyGranted("ROLE_SUPER_USER") ) 
        chain action: 'list', params: [id: user.userId]
     else 
        chain action: 'edit', params: [id: user.userId]
    

在 UserHelper.groovy 中,此方法出现错误

       static def bindPassword(UserWS newUser, UserWS oldUser, GrailsParameterMap params, flash) 
       if (oldUser) 
        // validate that the entered confirmation password matches the users existing password
        if (params.newPassword) 

            //read old password directly from DB. API does not reveal password hashes
            def oldPassword = UserDTO.get(oldUser.userId).password

            PasswordEncoder passwordEncoder = Context.getBean(Context.Name.PASSWORD_ENCODER)
            //fake user details so we can verify the customers password
            //should we move this to the server side validation?
            CompanyUserDetails userDetails = new CompanyUserDetails(
                    oldUser.getUserName(), oldPassword, true, true, true, true,
                    Collections.EMPTY_LIST, null,null,oldUser.getUserId(), oldUser.getMainRoleId(), oldUser.getEntityId(),
                    oldUser.getCurrencyId(), oldUser.getLanguageId()
            )
            if (!passwordEncoder.isPasswordValid(oldPassword, params.oldPassword, userDetails)) 
                flash.error = 'current.password.doesnt.match.existing'
                return
            

         else 
            newUser.setPassword(null)
        
    

    // verify passwords only when new password is present
    if (params.newPassword) 
        if (params.newPassword == params.verifiedPassword) 
            if (params.newPassword)
                newUser.setPassword(params.newPassword)
         else 
            flash.error = 'passwords.dont.match'
        
     else 
        newUser.setPassword(null)
    
    

我的CompanayUserDetails.java

 package com.sapienter.jbilling.client.authentication;

 import com.sapienter.jbilling.server.user.db.UserDTO;
 import org.springframework.security.core.GrantedAuthority;
 import grails.plugin.springsecurity.userdetails.GrailsUser;
 import java.util.Collection;
 import java.util.Locale;


public class CompanyUserDetails extends GrailsUser 

private final UserDTO user;
private final Locale locale;
private final Integer mainRoleId;
private final Integer companyId;
private final Integer currencyId;
private final Integer languageId;

 public CompanyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
                          boolean credentialsNonExpired, boolean accountNonLocked,
                          Collection<GrantedAuthority> authorities,
                          UserDTO user, Locale locale,
                          Integer id, Integer mainRoleId, Integer companyId, Integer currencyId, Integer languageId) 

    super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id);

    this.user = user;
    this.locale = locale;
    this.mainRoleId = mainRoleId;
    this.companyId = companyId;
    this.currencyId = currencyId;
    this.languageId = languageId;



   public UserDTO getUser() 
    return user;
  


   public String getPlainUsername() 
    return user.getUserName();
  


public Locale getLocale() 
    return locale;



public Integer getMainRoleId() 
    return mainRoleId;



public Integer getUserId() 
    return (Integer) getId();



public Integer getCompanyId() 
    return companyId;



public Integer getCurrencyId() 
    return currencyId;



public Integer getLanguageId() 
    return languageId;


  @Override
  public String toString() 
    final StringBuilder sb = new StringBuilder();
    sb.append("CompanyUserDetails");
    sb.append("id=").append(getId());
    sb.append(", username=").append("'").append(getUsername()).append("'");
    sb.append(", mainRoleId=").append(getMainRoleId());
    sb.append(", companyId=").append(getCompanyId());
    sb.append(", currencyId=").append(getCurrencyId());
    sb.append(", languageId=").append(getLanguageId());
    sb.append(", enabled=").append(isEnabled());
    sb.append(", accountExpired=").append(!isAccountNonExpired());  
    sb.append(", credentialsExpired=").append(!isCredentialsNonExpired());
    sb.append(", accountLocked=").append(!isAccountNonLocked());
    sb.append('');
    return sb.toString();
    
 

【问题讨论】:

【参考方案1】:

好吧,您将 null 传递给 UserDTO 的构造函数

Collection<GrantedAuthority> authorities, UserDTO user, Locale locale,

你已经过去了

Collections.EMPTY_LIST, null,null

所以getPlainUsername 当然会失败

【讨论】:

我需要提供什么来代替 null。如果我提供 oldUser.getUser(),您能否建议我。它显示错误为“未找到此类方法异常” 如果没有真正了解你的代码,我猜你会使用UserDTO.get(oldUser.userId)返回的值【参考方案2】:

致电new CompanyUserDetails

CompanyUserDetails userDetails = new CompanyUserDetails(
    oldUser.getUserName(), oldPassword, true, true, true, true,
    Collections.EMPTY_LIST, null, <--- param $8 is null

以及定义

 public CompanyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
     boolean credentialsNonExpired, boolean accountNonLocked,
     Collection<GrantedAuthority> authorities,
     UserDTO user, <--- param #8

最后是 NPE 在您致电 getPlainUsername

return user.getUserName();

NPE,无法调用空 user 对象的方法。

【讨论】:

【参考方案3】:

因此,要了解您的问题,您确实需要了解错误代码:

java.lang.NullPointerException 在 com.sapienter.jbilling.client.authentication.CompanyUserDetails.getPlainUsername(CompanyUserDetails.java:84)

根据我的编辑器第 84 行是

 sb.append(", languageId=").append(getLanguageId());

我建议将所有这些设置为一个值作为测试集

private final Integer mainRoleId=0;
private final Integer companyId=0;
private final Integer currencyId=0;
private final Integer languageId=0;

然后改变

this.mainRoleId = mainRoleId;
    this.companyId = companyId;
    this.currencyId = currencyId;
    this.languageId = languageId

if (mainRoleId)   this.mainRoleId = mainRoleId;
if (companyId)     this.companyId = companyId; 
if (currencyId)     this.currencyId = currencyId; 
if (languageId )     this.languageId = languageId 

糟糕的编码会导致糟糕的问题

【讨论】:

以上是关于使用 PlainUsername 的空指针异常的主要内容,如果未能解决你的问题,请参考以下文章

java中的空指针异常怎么解决

getLatitude 上的空指针异常

获取地图上的空指针异常

Grails 渲染插件的空指针异常

使用 Eclipse 插件追加新谷歌的空指针异常

自定义 Adapter 的 getView() 中的空指针异常