首页 > 解决方案 > 错误:使用此用户名的用户不存在:使用弹簧安全时

问题描述

我正在使用 Spring Boot + Spring Security 构建后端并使用 Postman 对其进行测试。对于前端,我将使用 Android 应用程序。

实施http basic auth

当我单击 Postman 中的身份验证选项卡并从下拉框中选择基本身份验证,然后我在那里输入用户名和密码字段时,它工作得很好。但是当我发送原始 JSON 请求正文时,我收到以下错误:

org.springframework.security.authentication.InternalAuthenticationServiceException: User doesn't exist with this username:

我认为这是由这个类引起的

CustomUserDetailsS​​ervice.java

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        CustomUserDetails userDetails = null;

        if(user != null){
            userDetails = new CustomUserDetails();
            userDetails.setUser(user);
        }else{
            throw new UserNotFoundException("User doesn't exist with this username: " + username);
        }
        return userDetails;

    }

}

但我不确定为什么它适用于 Postman auth 下拉框。

这是我使用的更多代码:

安全配置.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(encodePWD());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.csrf().disable();
        http
                .httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/rest/**").permitAll()
                .and()
                .authorizeRequests()
                .antMatchers("/secure/**").hasAnyRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll();

    }

    @Bean
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder();
    }

}

CustomUserDetailsS​​ervice.java

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        CustomUserDetails userDetails = null;

        if(user != null){
            userDetails = new CustomUserDetails();
            userDetails.setUser(user);
        }else{
            throw new UserNotFoundException("User doesn't exist with this username: " + username);
        }
        return userDetails;

    }

}

CustomUserDetails.java

@Getter
@Setter
public class CustomUserDetails implements UserDetails {
    private User user;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole())).collect(Collectors.toSet());
    }
    @Override
    public String getPassword() {
        return user.getPassword();
    }
    @Override
    public String getUsername() {
        return user.getUsername();
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }
}

我也使用它来登录用户并检查数据库中是否匹配一个。

@PostMapping("/loginuser")
    ResponseEntity<Object> login(@RequestBody User user) {
        List<User> userList = userRepository.findByUsernameAndPassword(user.getUsername(), user.getPassword());
        if (userList.size() != 1) {
            throw new UserNotFoundException("Entity not found");
        } else {
            return new ResponseEntity<>(userList.get(0), HttpStatus.OK);
        }
    }

甚至可以https basic auth用于休息服务器api吗?

或者我是否必须对 OAuth 等令牌使用一些身份验证?

更新

在此处输入图像描述

标签: javaspring-bootspring-security

解决方案


如果使用 Postman Authorization 选项卡,Postman 会构造相应的 Authorization header Authorization: Basic <credentials>,其中credentials是用户名和密码的 Base64 编码。

您可以在 Postman 请求中看到此标头,单击标头并隐藏。

Spring Security HTTP 基本身份验证需要此标头。如果您只是在请求正文中将用户名和密码作为 JSON 发布,则 Spring Security HTTP 基本身份验证无法从标头中提取用户名。因此,user等于null并抛出异常。


推荐阅读