【发布时间】: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 教程严重过时,请使用官方文档
标签: spring-boot kotlin spring-security cors