如何在Spring Security filter中授权CORS

velaa5lx  于 2023-10-20  发布在  Spring
关注(0)|答案(1)|浏览(105)

我试图用Sping Boot 和Spring Security构建一个REST API,但是我遇到了一个问题,因为CORS,任何对/login端点的请求都被阻止了,我不知道如何允许它。
以下是每当我在前端应用程序中发送登录请求时,我检查开发人员工具的网络选项卡时得到的结果:

下面是我的SecurityConfig.java文件(为了简洁起见,我省略了导入):

@EnableWebSecurity(debug = true)
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final AuthenticationUserDetailService authenticationUserDetailService;
    private final PasswordEncoder passwordEncoder;
    @Value("${jwt.secret}")
    private String jwtSecret;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.cors();
        http.authorizeRequests().antMatchers("/login").permitAll();
        http.authorizeRequests().antMatchers("/").permitAll();
        http.authorizeRequests().antMatchers("/api/teachers/**").hasAuthority("TEACHER");
        http.authorizeRequests().antMatchers("/api/students/**").hasAuthority("STUDENT");
        http.authorizeRequests().antMatchers("/api/**").hasAuthority("ADMIN");

        http.authorizeRequests().anyRequest().authenticated();
        //http.authorizeRequests().anyRequest().permitAll();
        http.addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtSecret));
        http.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtSecret));
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

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

下面是我的JwtAuthenticationFilter.java文件:

public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private final AuthenticationManager authenticationManager;
    private final String jwtSecret;

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager, String jwtSecret) {
        this.authenticationManager = authenticationManager;
        this.jwtSecret = jwtSecret;
        setFilterProcessesUrl("/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            LoginRequest credentials = new ObjectMapper()
                    .readValue(request.getInputStream(), LoginRequest.class);

            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            credentials.getUsername(),
                            credentials.getPassword(),
                            new ArrayList<>())
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        User user = (User) authResult.getPrincipal();

        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, jwtSecret.getBytes())
                .claim("role", authResult.getAuthorities().iterator().next().getAuthority())
                .setSubject(user.getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + 24 * 3600 * 1000))
                .compact();

        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write("{\"token\":\"" + token + "\"}");
    }
}

我已经尝试了我在网上找到的每一个解决方案,我已经没有办法了。如何从任何来源为我的/login端点授权CORS?
多谢了!

tkclm6bt

tkclm6bt1#

您必须提供CorsConfigurationSource类型的Bean,并告诉Spring Security在CorsFilter中使用该配置源,并将其放置在身份验证和授权过滤器之前。
首先,定义CorsConfigurationSource Bean:

@Bean
CorsConfigurationSource corsConfigurationSource() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    config.addAllowedOrigin("http://localhost:3000");
    source.registerCorsConfiguration("/**", config);
    return source;
}

然后,告诉Spring Security使用默认值配置CORS:

@Override
protected void configure(HttpSecurity http) throws Exception {
    ...
    http.cors(Customizer.withDefaults());
    ...
}

相关问题