【问题标题】:401 Unauthorized on authenticationManager.authenticate() (Spring Security)401 在 authenticationManager.authenticate() 上未经授权(Spring Security)
【发布时间】:2020-11-12 23:36:52
【问题描述】:

401 Unauthorized 在尝试登录时产生,而注册工作正常。

在调试期间,我发现在调用UserController 的方法authenticationManager.authenticate() 的行上给出了响应。我注意到的另一件事是,由于某种原因,我在使用 JPA 存储库而不是 DAO 时没有遇到这个问题。 我正在使用 PostgreSQL

如果UserController,下面是对应方法的代码:

    @RequestMapping(path = "/auth", method = RequestMethod.POST)
    @ResponseStatus(value = HttpStatus.OK)
    public AuthResponse authenticate(@RequestBody AuthRequest req){
        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(req.getUsername(), req.getPassword()));
        String token = jwtService.generateToken(req.getUsername());
        return new AuthResponse(token);
    }

JwtFilter.doFilterInternal():

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        String authorizationHeader = httpServletRequest.getHeader("Authorization");
        String jwtToken = null;
        String username = null;
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer")) {
            jwtToken = authorizationHeader.substring(7);
            username = jwtService.extractUsername(jwtToken);
        }
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if (jwtService.validateToken(jwtToken, userDetails.getUsername())) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities()
                );
                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

SecurityConfig.configure():

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().cors().disable()
                .authorizeRequests()
                .anyRequest().permitAll()
                .and().addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().httpBasic();
    }

UserService.loadUserByUsername():

@Service
public class UserService implements IUserService, UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User userByName = userDao.getUserByUsername(s);
        return new org.springframework.security.core.userdetails.User(userByName.getUsername(), userByName.getPassword(), userByName.getAuthorities());
    }
}

DAO 查询:

@Override
public User getUserByUsername(String username) {
    return jdbcTemplate.queryForObject("SELECT * FROM user_table WHERE username = ?", new Object[]{username}, User.class);
}

【问题讨论】:

    标签: spring spring-boot spring-security


    【解决方案1】:

    这可能是 JWT 问题。 在行中:.and().addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) 使用 Debug 看看,你有什么作为参数。

    【讨论】:

      【解决方案2】:

      如果你看documentation

      An AuthenticationManager must honour the following contract concerning exceptions:
      
      A DisabledException must be thrown if an account is disabled and the AuthenticationManager can test for this state.
      A LockedException must be thrown if an account is locked and the AuthenticationManager can test for account locking.
      A BadCredentialsException must be thrown if incorrect credentials are presented. Whilst the above exceptions are optional, an AuthenticationManager must always test credentials.
      Exceptions should be tested for and if applicable thrown in the order expressed above (i.e. if an account is disabled or locked, the authentication request is immediately rejected and the credentials testing process is not performed). This prevents credentials being tested against disabled or locked accounts.
      

      我猜你的身份验证是抛出这三个异常之一(或者可能是其他一些异常)。您需要查看日志以确定是哪一个,或者捕获异常并进行调试。

      【讨论】:

        【解决方案3】:

        问题是查询没有返回预期值。我改变了:

         @Override
        public User getUserByUsername(String username) {
            List<User> userList = jdbcTemplate.query("SELECT * FROM user_table WHERE username = ?", new Object[]{username}, (resultSet,i) -> {
                System.out.println(1);
                return new User(resultSet.getInt("id"),
                        resultSet.getString("username"),
                        resultSet.getString("password"),
                        resultSet.getString("role"));
            });
            return userList.get(0);
        }
        

        【讨论】:

          猜你喜欢
          • 2021-02-02
          • 2017-05-26
          • 2022-01-21
          • 2019-08-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-12
          • 2021-02-25
          相关资源
          最近更新 更多