막상 짜고 나니 Interceptor에서 처리해야 해서 기록용으로 남긴다.
class CpApiAuthFilter : AbstractPreAuthenticatedProcessingFilter() {
val log = LoggerFactory.getLogger(javaClass)!!
override fun getPreAuthenticatedCredentials(request: HttpServletRequest): CpCredential {
val apiKey:String? = request.getHeader("x-sample-api-key")
val cpId:String? = request.getHeader("x-sample-cp-id")
log.debug("api key auth: cpId=$cpId,apiKey=$apiKey")
return CpCredential(apiKey, cpId)
}
override fun getPreAuthenticatedPrincipal(request: HttpServletRequest): Any {
return ""
}
}
data class CpCredential(
val apiKey:String? = null,
val cpId:String? = null
){
fun isValid(): Boolean {
if(apiKey.isNullOrBlank() || cpId == null || apiKey?.length!! < 5 )
return false
try {
cpId.toLong()
} catch (e:Exception){
return false
}
return true
}
fun getCpId():Long = cpId!!.toLong()
}
class CpApiAuthManager
@Autowired constructor(private val repository: CpRepository)
: AuthenticationManager {
override fun authenticate(authentication: Authentication): Authentication {
val credential = authentication.principal as CpCredential
if(credential.isValid().not())
throw BadCredentialsException("apiKey, cpId not found or not expected value.")
val cpId = credential.getCpId()
val cp = repository.findOne(cpId)
if (cp == null || !cp.status)
throw BadCredentialsException("cp not found or cp expired.")
if(cp.apiKey != credential.apiKey)
throw BadCredentialsException("cpId and apiKey do not matched.")
authentication.isAuthenticated = true
return authentication
}
}
인증용 Filter, Manager는 위처럼 생성.security에 적용하는 건 아래 처럼 하면 됨.
@Bean
@Order(1)
fun webSecurityConfigurerAdapter(): WebSecurityConfigurerAdapter {
return object : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.addFilter(CpApiAuthFilter(CpApiAuthManager(cpRepository)))
http.headers().frameOptions().disable().xssProtection().xssProtectionEnabled(true)
.and().contentTypeOptions()
.and().cacheControl().disable()
.and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
}
}
}
일부 코드만 발췌한거라 동작을 안할 수도 있다.ㅎㅎㅎ