You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用正确账号密码仍出现401未授权——Spring Boot Security认证问题

问题分析

你的代码存在三个关键问题导致认证失败:

  1. 缺少PasswordEncoder Bean:Spring Security 2.x及以后版本要求必须显式提供密码编码器,否则无法完成密码校验,默认用户user的密码验证也会失败。
  2. 注册接口被拦截:当前配置要求所有请求都必须认证,但POST /user是注册接口,需要允许匿名访问,否则连新用户都无法创建。
  3. 未配置用户信息来源:如果使用默认用户,需要确保其密码使用对应的编码器处理,或者自定义用户查询逻辑。

修复步骤

1. 完善Security配置

修改SecurityConfig,添加密码编码器Bean,并放开注册接口的匿名访问权限:

package com.api.business_products_management.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                // 允许注册接口匿名访问
                .requestMatchers("/user").permitAll()
                // 其他所有请求需要认证
                .anyRequest().authenticated()
                .and()
            .httpBasic();
        return http.build();
    }
}

2. 优化Controller的密码编码器使用

将密码编码器注入到Controller中使用,而非每次创建新实例:

package com.api.business_products_management.controllers;

import com.api.business_products_management.dtos.UserDto;
import com.api.business_products_management.models.UserModel;
import com.api.business_products_management.services.UserService;
import jakarta.validation.Valid;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping("/user")
public class UserController {

    final UserService userService;
    final PasswordEncoder passwordEncoder;

    // 注入PasswordEncoder
    public UserController(UserService userService, PasswordEncoder passwordEncoder) {
        this.userService = userService;
        this.passwordEncoder = passwordEncoder;
    }

    @PostMapping
    public ResponseEntity<Object> saveUser(@RequestBody @Valid UserDto userDto) {
        var userModel = new UserModel();
        BeanUtils.copyProperties(userDto, userModel);
        userModel.setPassword(passwordEncoder.encode(userModel.getPassword()));
        return ResponseEntity.status(HttpStatus.CREATED).body(userService.save(userModel));
    }
}

3. 配置默认用户(可选)

如果需要继续使用Spring Security的默认用户,可在SecurityConfig中添加内存用户配置:

import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

// 在SecurityConfig中添加该Bean
@Bean
public InMemoryUserDetailsManager userDetailsService() {
    UserDetails user = User.withUsername("user")
        .password(passwordEncoder().encode("your-custom-password")) // 设置自定义默认密码
        .roles("USER")
        .build();
    return new InMemoryUserDetailsManager(user);
}

注:自定义用户后,Spring Boot不会再自动生成随机密码,需手动设置密码。

测试验证

  1. 重启应用后,先调用POST /user接口创建新用户(无需认证)
  2. 使用创建的用户或配置的默认用户,通过Postman的"Basic Auth"方式输入用户名密码,访问其他需要认证的接口,即可正常通过授权。

内容的提问来源于stack exchange,提问作者Routfin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 06:06:45