Spring-Security:使用 CORS Preflights 获得 401(尽管 http.cors())
Posted
技术标签:
【中文标题】Spring-Security:使用 CORS Preflights 获得 401(尽管 http.cors())【英文标题】:Spring-Security: Getting 401s with CORS Preflights (despite http.cors()) 【发布时间】:2020-08-26 17:22:20 【问题描述】:对于初学者,我想使用基本身份验证来保护我的 rest-api 的一部分。 当我尝试从反应客户端访问端点时,我在预检请求中不断收到 401。
我尝试遵循本指南但没有成功: https://www.baeldung.com/spring-security-cors-preflight
我不确定这是否是问题的一部分,但另一部分只能通过某些自定义 http 标头访问。
我正在使用方法安全性:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = false)
class MethodSecurityConfig : GlobalMethodSecurityConfiguration()
override fun customMethodSecurityMetadataSource(): MethodSecurityMetadataSource = SecurityMetadataSource()
override fun accessDecisionManager(): AccessDecisionManager = super.accessDecisionManager().apply
this as AbstractAccessDecisionManager
decisionVoters.add(PrivilegeVoter())
这是我的安全配置:
@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
class SecurityConfig : WebSecurityConfigurerAdapter()
private val deviceRequestHeaderName: String = "X-DEVICE-ID"
private val platformRequestHeaderName: String = "X-PLATFORM-ID"
@Autowired
lateinit var users: AppUserRepository
@Autowired
lateinit var backendUsers: BackendUserRepository
@Autowired
lateinit var roles: RoleRepository
val authManager by lazy authenticationManager()
private val authProvider by lazy
PreAuthenticatedAuthenticationProvider().apply
setPreAuthenticatedUserDetailsService
val authId = it.principal as UserAuthId
if (authId.deviceId == null) throw UsernameNotFoundException("No device-id to search for.")
if (authId.platform == null) throw UsernameNotFoundException("Platform not specified.")
val platform = try
ApplicationPlatform.valueOf(authId.platform)
catch (e: IllegalArgumentException)
throw UsernameNotFoundException("Unknown platform $authId.platform.")
val existingUser = users.findByUserDeviceIdAndPlatform(authId.deviceId, platform)
if (existingUser != null) return@setPreAuthenticatedUserDetailsService existingUser
users.save(AppUser(authId.deviceId, platform, roles))
val passwordEncoder by lazy BCryptPasswordEncoder()
private val deviceIdFilter by lazy
HeaderFieldAuthFilter(deviceRequestHeaderName, platformRequestHeaderName).apply
setAuthenticationManager(authManager)
override fun configure(auth: AuthenticationManagerBuilder) = auth
authenticationProvider(authProvider)
val userDetailsService = BackendUserDetailsService(backendUsers)
userDetailsService(userDetailsService).passwordEncoder(passwordEncoder)
override fun configure(http: HttpSecurity) = http
session
sessionCreationPolicy(SessionCreationPolicy.STATELESS)
exceptionHandling()
addFilter(deviceIdFilter)
authorizeRequests().anyRequest().authenticated()
csrf().disable()
httpBasic()
cors().configurationSource request ->
CorsConfiguration().apply
allowedOrigins = listOf(ALL)
allowedMethods = listOf(GET, POST, DELETE, PUT, OPTIONS).map it.name
allowedHeaders = listOf(ALL)
allowCredentials = true
maxAge = 3600
@Bean
fun auditorProvider(): AuditorAware<User> = AuditorAware<User>
val authentication = SecurityContextHolder.getContext().authentication
val user = authentication.run if (isAuthenticated) principal as? User else null
return@AuditorAware Optional.ofNullable(user)
【问题讨论】:
Baeldung 教程严重过时,请使用官方文档 【参考方案1】:我可以通过手动从身份验证中排除预检请求来解决。 添加这个
antMatchers(OPTIONS, "/**").permitAll()
authorizeRequests()
配置可以实现这一点。
请注意,Options 是对 HttpMethod 枚举值的直接引用,像这样导入
import org.springframework.http.HttpMethod.*
帮助我实现目标的 *** 帖子:
Response for preflight has invalid HTTP status code 401 - Spring How to configure CORS in a Spring Boot + Spring Security application?最初我认为这应该由 cors 配置处理 - 显然不是。
【讨论】:
【参考方案2】:要为单个休息端点启用 CORS,您可以使用以下命令对其进行注释:
@CrossOrigin
要允许所有端点使用 CORS,您可以使用这样的 bean:
@Bean
public WebMvcConfigurer corsConfigurer()
return new WebMvcConfigurerAdapter()
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
.allowedHeaders("*");
;
【讨论】:
将@CrossOrigin 放在单个端点上并不能解决我项目中该端点的问题。选项请求得到 401 响应。 我明天将测试 WebMvcConfigurerAdapter 建议。以上是关于Spring-Security:使用 CORS Preflights 获得 401(尽管 http.cors())的主要内容,如果未能解决你的问题,请参考以下文章
Spring-Security OAuth WebMVC 无效的 CORS 请求
如何为 Webflux、Spring-Security、okta-spring-boot-starter 和 Okta-React 正确使用 CORS?