如何在 Spring Security 过滤器中授权 CORS
Posted
技术标签:
【中文标题】如何在 Spring Security 过滤器中授权 CORS【英文标题】:How to authorize CORS in Spring Security filter 【发布时间】: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 类中。 这能回答你的问题吗? How to configure CORS in a Spring Boot + Spring Security application? CORS 是 Spring Security 中回答最多的问题。我们每周收到大约 5 个关于它的问题。提问前请使用搜索功能。 Spring 安全文档有一整章是关于 CORS 的,这里有 100 多个关于 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());
...
【讨论】:
以上是关于如何在 Spring Security 过滤器中授权 CORS的主要内容,如果未能解决你的问题,请参考以下文章
如何避免自定义过滤器在spring-security中为不安全的url运行
如何在 Spring Security 过滤器中授权 CORS
如何使用带有多个过滤器和 Spring Security 的 Spring DelegatingFilterProxy?
如何使用 Spring Security 为微服务创建自定义安全过滤器