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

Spring Security自定义登录成功后放行页面的问题求助

问题分析与解决方案

你遇到的405错误根源在于Spring Security的formLogin配置与自定义/login接口冲突:formLogin默认会接管/login端点的处理逻辑,当你通过Angular发送POST请求到/login时,Security过滤器会拦截该请求,认为请求方法不被允许,从而返回405状态码。

以下是正确的实现步骤:


1. 调整Spring Security配置

移除formLogin相关配置(因为你使用自定义REST登录接口,而非Security默认的表单登录页面),同时配置CORS支持跨域请求(适配Angular前端),并明确权限规则:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class Config {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(10);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
                // 配置CORS,允许Angular前端的跨域请求
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/login").permitAll() // 允许POST请求访问/login
                .antMatchers("/welcome").hasRole("ADMIN") // /welcome仅允许ADMIN角色访问
                .anyRequest().authenticated()
                // 配置会话管理,保持登录状态以便后续访问受保护资源
                .and()
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));

        return http.build();
    }

    // 暴露AuthenticationManager,用于自定义登录逻辑中的用户验证
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }

    // CORS配置,根据你的Angular实际端口调整
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("Content-Type"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    public InMemoryUserDetailsManager userDetailsManager() {
        var linda = User.builder()
                .username("linda")
                .password(passwordEncoder().encode("pass"))
                .roles("ADMIN")
                .build();
        return new InMemoryUserDetailsManager(linda);
    }
}

2. 修改LoginController实现正确认证逻辑

使用Spring Security的AuthenticationManager验证用户凭据,并将认证结果存入SecurityContext,确保后续请求能识别用户登录状态:

@RestController
public class LoginController {

    private final AuthenticationManager authenticationManager;

    // 构造注入AuthenticationManager
    public LoginController(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestBody User user) {
        try {
            // 验证用户名和密码
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword())
            );
            // 将认证信息存入SecurityContext,标记用户已登录
            SecurityContextHolder.getContext().setAuthentication(authentication);
            return ResponseEntity.ok("Access granted");
        } catch (BadCredentialsException e) {
            return ResponseEntity.badRequest().body("Access denied");
        }
    }
}

3. 确保User实体类的正确性

User类需要包含username和password的getter方法,以便Spring能正确解析请求体:

public class User {
    private String username;
    private String password;

    // 构造器、getter和setter
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

测试验证

  1. Angular前端发送POST请求到/login,携带JSON体:{"username":"linda", "password":"pass"},会返回200 OK。
  2. 登录成功后,访问/welcome端点,会返回正常响应(已认证状态)。
  3. 若登录失败或未登录时访问/welcome,会返回403 Forbidden。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:20:35