【问题标题】:How to authorize CORS in Spring Security filter如何在 Spring Security 过滤器中授权 CORS
【发布时间】:2021-10-28 03:15:52
【问题描述】:

我正在尝试使用 Spring Boot 和 Spring Security 构建一个 REST API,但我遇到了一个问题,即对 /login 端点的任何请求由于 CORS 而被阻止,我不知道如何允许它。

每当我在前端应用程序中发送登录请求时检查开发工具的网络选项卡时,我会得到以下结果:

这是我的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?

非常感谢!

【问题讨论】:

  • 你能发布你的登录控制器吗?这里有2个问题。 1.您面临的 CORS 问题,因为您的 UI 在实际 POST 调用之前进行了 OPTIONS 调用。 2. 403 理想情况下不应该存在,因为您在 ant matcher 中排除了 /login。所以只想交叉检查
  • @SridharPatnaik 我没有登录控制器。一切都在 JwtAuthenticationFilter 类中。
  • CORS 是 Spring Security 中回答最多的问题。我们每周收到大约 5 个关于它的问题。提问前请使用搜索功能。 Spring 安全文档有一整章是关于 CORS 的,这里有 100 多个关于 CORS 的答案。投票关闭重复。

标签: java spring spring-boot spring-security cors


【解决方案1】:

您必须提供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());
    ...
}

【讨论】:

    猜你喜欢
    • 2021-10-31
    • 2011-10-29
    • 2015-10-13
    • 1970-01-01
    • 2023-03-05
    • 2016-11-10
    • 2018-12-11
    • 2016-06-25
    相关资源
    最近更新 更多