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

Spring Security配置无效:添加依赖及配置后仍返回401错误求助

Spring Security 401未授权问题排查

我是Spring Security新手,在项目中添加Spring Security依赖后立即出现401未授权错误。编写了Security配置类后问题依旧,以下是我的配置类、服务类及控制器类代码,请帮忙排查问题:

配置类代码

package com.hasti.birdy.portfolio.user.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.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class UserConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) {
    try {
        System.out.println("filtering certain requests");
        return httpSecurity.csrf()
        .disable()          
        .authorizeHttpRequests()
        .requestMatchers("/api/user/**")
        .permitAll()
        .and()
        .httpBasic()
        .and()
        .build();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}

@Bean
public UserSecurity getUserSecurity() {
    return new UserSecurity();
}
}

服务类代码

package com.hasti.birdy.portfolio.user.service;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.hasti.birdy.portfolio.user.config.UserSecurity;
import com.hasti.birdy.portfolio.user.dto.PermissionDto;
import com.hasti.birdy.portfolio.user.dto.UserDto;
import com.hasti.birdy.portfolio.user.mapper.PermissionMapper;
import com.hasti.birdy.portfolio.user.mapper.RoleMapper;
import com.hasti.birdy.portfolio.user.mapper.UserMapper;
import com.hasti.birdy.portfolio.user.model.Permission;
import com.hasti.birdy.portfolio.user.model.Role;
import com.hasti.birdy.portfolio.user.model.UserModel;
import com.hasti.birdy.portfolio.user.repository.RoleRepository;
import com.hasti.birdy.portfolio.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
@RequiredArgsConstructor
public class UserService {

private final UserMapper userMapper;
private final RoleMapper roleMapper;
private final PermissionMapper permissionMapper;
private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final UserSecurity userSecurity;
public String createAdmin(UserDto userDto)
{
    UserModel userModel = userMapper.map(userDto);
    Role role = roleRepository.findAdminRole();
    userModel.setEncryptedPassword(userSecurity.getPasswordEncoder().encode(userDto.getPassword()));
    userModel.setRole(role);
    userRepository.save(userModel);
    return "created";
}

public String createCustomer(UserDto userDto)
{
    UserModel userModel = userMapper.map(userDto);
    Role role = roleRepository.findCustomerRole();
    userModel.setEncryptedPassword(userSecurity.getPasswordEncoder().encode(userDto.getPassword()));
    userModel.setRole(role);
    userRepository.save(userModel);
    return "created";
}


}

控制器类代码

package com.hasti.birdy.portfolio.user.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.hasti.birdy.portfolio.user.dto.UserDto;
import com.hasti.birdy.portfolio.user.service.UserService;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/user")
public class UserController {

private final UserService userService;
@PostMapping("/hsstudio/admin")
public ResponseEntity<String> createAdmin(@RequestBody UserDto userDto)
{
    userService.createAdmin(userDto);
    return ResponseEntity.status(HttpStatus.CREATED).body("created Admin");
}
@PostMapping()
public ResponseEntity<String> createCustomer(@RequestBody UserDto userDto)
{
    userService.createCustomer(userDto);
    return ResponseEntity.status(HttpStatus.CREATED).body("created customer ");
}

    }

问题原因及修复方案

核心问题1:SecurityFilterChain构建失败后返回null

你的filterChain方法中,当构建HttpSecurity出现异常时直接返回null,导致Spring Security无法加载自定义过滤规则,转而启用默认安全配置——默认所有请求都需要HTTP Basic认证,因此你配置的/api/user/**放行规则完全不生效,访问时直接返回401。

核心问题2:缺少剩余请求的授权规则兜底

配置中仅定义了/api/user/**的放行规则,但未明确剩余请求的处理逻辑,Spring Security的默认行为可能引发非预期的认证拦截。

修复步骤

  1. 修正SecurityFilterChain的构建逻辑
    移除try-catch中的返回null逻辑,改为直接抛出异常,确保自定义过滤链能正常加载:

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        System.out.println("filtering certain requests");
        return httpSecurity.csrf()
                .disable()          
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/api/user/**").permitAll()
                        .anyRequest().authenticated() // 明确剩余请求需要认证
                )
                .httpBasic()
                .and()
                .build();
    }
    
  2. 确保PasswordEncoder正确注册为Bean
    你的UserSecurity类中使用了密码编码器,但需要确保它被Spring容器管理。可以在UserSecurity中添加:

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

    或者直接在UserConfig中注册该Bean,避免依赖UserSecurity。

  3. 验证请求路径匹配
    控制器中的/api/user和/api/user/hsstudio/admin都能被/api/user/**规则匹配到,这部分无需修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:54:57