security遇java.lang.IllegalArgumentException Cannot pass null or empty values toconstructor

x33g5p2x  于2022-02-12 转载在 Java  
字(3.2k)|赞(0)|评价(0)|浏览(413)

1.遇到这个报错大概都是因为在实现UserDetailService接口,执行查库操作发现有null值

2.确定null值的字段

在测试类中

  1. //注入Mapper
  2. @Autowired
  3. private UserMapper userMapper;
  4. @Test
  5. void contextLoads() {
  6. //调用方法
  7. System.out.println(userMapper.getUserByPhoneNumber("1"));
  8. }
  9. //打印的结果
  10. User{phoneNumber='null', password='1'}

发现数据库的字段phoneNumber为空值,能查出password,但phoneNumber找不到。

最后了解发现,在数据库表中的字段带有_,比如phone_number,在实体类中,如果你使用小驼峰需要在Yaml这样配置开启小驼峰规则

  1. mybatis:
  2. configuration:
  3. map-underscore-to-camel-case: true

还有一步就是在Mapper中加入

  1. @Select("select phone_number,password from customer where phone_number=#{phoneNumber}")
  2. @Result(column = "phone_number",property = "phoneNumber",jdbcType = JdbcType.VARCHAR)
  3. Customer getUserByPhoneNumber(String phoneNumber);

3.More

在security中加入自己的验证规则可以实现AuthenticationProvide接口

  1. public class SmsCodeAuthenticationProvider implements AuthenticationProvider {
  2. @Autowired
  3. private UserDetailsService userDetailsService;
  4. @Override
  5. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  6. SmsCodeAuthenticationToken smsCodeAuthenticationToken = (SmsCodeAuthenticationToken) authentication;
  7. /**
  8. * 我的用户实体类实现了UserDetailer接口,userDetailsService也有我自己的实现类。
  9. *所有要使用security框架,进行查库操作用户实体类和XXXUserDetailService需要实现相应的接口才能把自己的规则加入到Security中
  10. */
  11. UserDetails user = userDetailsService.loadUserByUsername((String)smsCodeAuthenticationToken.getPrincipal());
  12. //用户user为空说明,数据库中查不到
  13. if(user == null){
  14. throw new InternalAuthenticationServiceException("用户不存在");
  15. }
  16. //下面是验证在数据库中查到的密码和用户输入的密码是否相同
  17. if(!new BCryptPasswordEncoder().matches(smsCodeAuthenticationToken.getCredentials().toString(),user.getPassword())){
  18. throw new BadCredentialsException("密码不正确");
  19. }
  20. //进入到SmsCodeAuthenticationToken类,将用户和用户权限存到SmsCodeAuthenticationToken对象中
  21. SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user,user.getAuthorities());
  22. authenticationResult.setDetails(smsCodeAuthenticationToken.getDetails());
  23. return authenticationResult;
  24. }
  25. @Override
  26. public boolean supports(Class<?> aClass) {
  27. return SmsCodeAuthenticationToken.class.isAssignableFrom(aClass);
  28. }
  29. public UserDetailsService getUserDetailsService() {
  30. return userDetailsService;
  31. }
  32. public void setUserDetailsService(UserDetailsService userDetailsService) {
  33. this.userDetailsService = userDetailsService;
  34. }
  35. }

SmsCodeAuthenticationToken类

  1. public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken {
  2. private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
  3. private final Object principal;
  4. private Object credentials;
  5. public SmsCodeAuthenticationToken(String mobile,String password) {
  6. super(null);
  7. this.principal = mobile;
  8. this.credentials=password;
  9. setAuthenticated(false);
  10. }
  11. public SmsCodeAuthenticationToken(Object principal,
  12. Collection<? extends GrantedAuthority> authorities) {
  13. super(authorities);
  14. this.principal = principal;
  15. super.setAuthenticated(true); // must use super, as we override
  16. }
  17. public Object getCredentials() {
  18. return this.credentials;
  19. }
  20. public Object getPrincipal() {
  21. return this.principal;
  22. }
  23. public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
  24. if (isAuthenticated) {
  25. throw new IllegalArgumentException(
  26. "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
  27. }
  28. super.setAuthenticated(false);
  29. }
  30. @Override
  31. public void eraseCredentials() {
  32. super.eraseCredentials();
  33. }
  34. }

相关文章

最新文章

更多