使用 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 的空指针异常的主要内容,如果未能解决你的问题,请参考以下文章