authenticaction, registration, login
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import com.aitrainer.api.ApiApplication
|
||||
import com.aitrainer.api.controller.ApplicationProperties
|
||||
import com.aitrainer.api.controller.Singleton
|
||||
import com.aitrainer.api.repository.ConfigurationRepository
|
||||
import org.aspectj.lang.JoinPoint
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.annotation.Before
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Suppress("unused")
|
||||
@Aspect
|
||||
@Component
|
||||
class AuthenticationControllerAspect {
|
||||
private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName)
|
||||
|
||||
@Autowired
|
||||
private lateinit var configurationRepository: ConfigurationRepository
|
||||
@Autowired
|
||||
private lateinit var properties: ApplicationProperties
|
||||
|
||||
@Before("execution(* com.aitrainer.api.security.JwtAuthenticationController.*(..))")
|
||||
fun customerControllerAspect(joinPoint: JoinPoint) {
|
||||
println("auth controller join")
|
||||
Singleton.checkDBUpdate(configurationRepository, properties)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import com.aitrainer.api.service.UserDetailsServiceImpl
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.BadCredentialsException
|
||||
import org.springframework.security.authentication.DisabledException
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
|
||||
|
||||
@Component
|
||||
@RestController
|
||||
//@CrossOrigin
|
||||
@RequestMapping("/api")
|
||||
class JwtAuthenticationController {
|
||||
@Autowired
|
||||
private val authenticationManager: AuthenticationManager? = null
|
||||
|
||||
@Autowired
|
||||
private val jwtTokenUtil: JwtTokenUtil? = null
|
||||
|
||||
@Autowired
|
||||
private val jwtUserDetailsService: UserDetailsServiceImpl? = null
|
||||
|
||||
@PostMapping("/authenticate")
|
||||
fun generateAuthenticationToken(@RequestBody authenticationRequest: JwtRequest): ResponseEntity<*> {
|
||||
|
||||
authenticate(authenticationRequest.username!!, authenticationRequest.password!!)
|
||||
|
||||
val userDetails = jwtUserDetailsService
|
||||
?.loadUserByUsername(authenticationRequest.username)
|
||||
val token: String = jwtTokenUtil!!.generateToken(userDetails!!)
|
||||
return ResponseEntity.ok<Any>(JwtResponse(token))
|
||||
}
|
||||
|
||||
private fun authenticate(username: String, password: String) {
|
||||
try {
|
||||
authenticationManager!!.authenticate(UsernamePasswordAuthenticationToken(username, password))
|
||||
} catch (e: DisabledException) {
|
||||
throw Exception("USER_DISABLED", e)
|
||||
} catch (e: BadCredentialsException) {
|
||||
throw Exception("INVALID_CREDENTIALS", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.stereotype.Component
|
||||
import java.io.IOException
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
import java.io.Serializable
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
|
||||
|
||||
@Component
|
||||
class JwtAuthenticationEntryPoint : AuthenticationEntryPoint, Serializable {
|
||||
@Throws(IOException::class)
|
||||
override fun commence(request: HttpServletRequest?, response: HttpServletResponse,
|
||||
authException: AuthenticationException?) {
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val serialVersionUID = -7858869558953243875L
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class JwtRequest : Serializable {
|
||||
var username: String? = null
|
||||
var password: String? = null
|
||||
|
||||
//default constructor for JSON Parsing
|
||||
constructor(username: String?, password: String?) {
|
||||
this.username = username
|
||||
this.password = password
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val serialVersionUID = 5926468583005150707L
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import com.aitrainer.api.service.UserDetailsServiceImpl
|
||||
import io.jsonwebtoken.ExpiredJwtException
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.filter.OncePerRequestFilter
|
||||
import java.io.IOException
|
||||
import javax.servlet.FilterChain
|
||||
import javax.servlet.ServletException
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
|
||||
@Component
|
||||
class JwtRequestFilter : OncePerRequestFilter() {
|
||||
@Autowired
|
||||
private val jwtUserDetailsService: UserDetailsServiceImpl? = null
|
||||
|
||||
@Autowired
|
||||
private val jwtTokenUtil: JwtTokenUtil? = null
|
||||
|
||||
//@Autowired
|
||||
//private lateinit var authenticationController: JwtAuthenticationController
|
||||
|
||||
@Throws(ServletException::class, IOException::class)
|
||||
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
|
||||
val requestTokenHeader = request.getHeader("Authorization")
|
||||
var username: String? = null
|
||||
var jwtToken: String? = null
|
||||
// JWT Token is in the form "Bearer token". Remove Bearer word and get only the Token
|
||||
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer")) {
|
||||
jwtToken = requestTokenHeader.substring(7)
|
||||
try {
|
||||
username = jwtTokenUtil!!.getUsernameFromToken(jwtToken)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
println("Unable to get JWT Token")
|
||||
} catch (e: ExpiredJwtException) {
|
||||
println("JWT Token has expired")
|
||||
}
|
||||
} else if (requestTokenHeader != null && requestTokenHeader.equals("1") ) {
|
||||
logger.warn("Authenticate")
|
||||
//val credentials: User = ObjectMapper().readValue(request.inputStream, User::class.java)
|
||||
|
||||
} else {
|
||||
logger.warn("JWT Token does not begin with Bearer String")
|
||||
}
|
||||
|
||||
//Once we get the token validate it.
|
||||
if (username != null && SecurityContextHolder.getContext().authentication == null) {
|
||||
val userDetails: UserDetails = jwtUserDetailsService!!.loadUserByUsername(username)
|
||||
|
||||
// if token is valid configure Spring Security to manually set authentication
|
||||
if (jwtTokenUtil!!.validateToken(jwtToken!!, userDetails)) {
|
||||
val usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.authorities)
|
||||
usernamePasswordAuthenticationToken.details = WebAuthenticationDetailsSource().buildDetails(request)
|
||||
// After setting the Authentication in the context, we specify
|
||||
// that the current user is authenticated. So it passes the Spring Security Configurations successfully.
|
||||
SecurityContextHolder.getContext().authentication = usernamePasswordAuthenticationToken
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response)
|
||||
}
|
||||
|
||||
/*private fun readUserCredentials(request: HttpServletRequest): UserCredentials? {
|
||||
return try {
|
||||
ObjectMapper().readValue(request.inputStream, UserCredentials::class.java)
|
||||
} catch (ioe: IOException) {
|
||||
throw BadCredentialsException("Invalid request", ioe)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class JwtResponse(val token: String) : Serializable {
|
||||
|
||||
companion object {
|
||||
private const val serialVersionUID = -8091879091924046844L
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import com.aitrainer.api.service.ServiceBeans
|
||||
import com.aitrainer.api.service.UserDetailsServiceImpl
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.config.http.SessionCreationPolicy
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
class JwtSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
@Autowired
|
||||
private val jwtAuthenticationEntryPoint: JwtAuthenticationEntryPoint? = null
|
||||
|
||||
@Autowired
|
||||
private val jwtUserDetailsService: UserDetailsServiceImpl? = null
|
||||
|
||||
@Autowired
|
||||
private val jwtRequestFilter: JwtRequestFilter? = null
|
||||
|
||||
@Autowired
|
||||
private val serviceBeans: ServiceBeans? = null
|
||||
|
||||
override fun configure(auth: AuthenticationManagerBuilder?) {
|
||||
auth!!.userDetailsService(jwtUserDetailsService).passwordEncoder(serviceBeans!!.passwordEncoder())
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Throws(Exception::class)
|
||||
override fun authenticationManagerBean(): AuthenticationManager {
|
||||
return super.authenticationManagerBean()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun configure(httpSecurity: HttpSecurity) {
|
||||
|
||||
// We don't need CSRF for this example
|
||||
httpSecurity.
|
||||
csrf().disable().
|
||||
// dont authenticate this particular request
|
||||
authorizeRequests().antMatchers("/api/authenticate").permitAll().
|
||||
// all other requests need to be authenticated
|
||||
anyRequest().authenticated().and().
|
||||
// make sure we use stateless session; session won't be used to
|
||||
// store user's state.
|
||||
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().
|
||||
// Add a filter to validate the tokens with every request
|
||||
//addFilterAt(JwtAuthenticationFilter(authenticationManagerBean()), UsernamePasswordAuthenticationFilter::class.java).
|
||||
addFilterAfter(jwtRequestFilter, UsernamePasswordAuthenticationFilter::class.java).
|
||||
sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.aitrainer.api.security
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.stereotype.Component
|
||||
import java.util.*
|
||||
import java.io.Serializable
|
||||
|
||||
import io.jsonwebtoken.Claims
|
||||
import io.jsonwebtoken.Jwts
|
||||
import io.jsonwebtoken.SignatureAlgorithm
|
||||
|
||||
|
||||
@Component
|
||||
class JwtTokenUtil : Serializable {
|
||||
@Value("\${jwt.secret}")
|
||||
private val secret: String? = null
|
||||
fun getUsernameFromToken(token: String?): String {
|
||||
return getClaimFromToken(token, Claims::getSubject)
|
||||
}
|
||||
|
||||
fun getIssuedAtDateFromToken(token: String?): Date {
|
||||
return getClaimFromToken<Date>(token, Claims::getIssuedAt)
|
||||
}
|
||||
|
||||
fun getExpirationDateFromToken(token: String?): Date {
|
||||
return getClaimFromToken<Date>(token, Claims::getExpiration)
|
||||
}
|
||||
|
||||
fun <T> getClaimFromToken( token: String?, claimsResolver: ( Claims.()-> T ) ): T {
|
||||
val claims: Claims = getAllClaimsFromToken(token)
|
||||
return claims.claimsResolver()
|
||||
}
|
||||
|
||||
private fun getAllClaimsFromToken(token: String?): Claims {
|
||||
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).body
|
||||
}
|
||||
|
||||
private fun isTokenExpired(token: String): Boolean {
|
||||
val expiration: Date = getExpirationDateFromToken(token)
|
||||
return expiration.before(Date())
|
||||
}
|
||||
|
||||
fun generateToken(userDetails: UserDetails): String {
|
||||
val claims: Map<String, Any> = HashMap()
|
||||
return doGenerateToken(claims, userDetails.username)
|
||||
}
|
||||
|
||||
private fun doGenerateToken(claims: Map<String, Any>, subject: String): String {
|
||||
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(Date(System.currentTimeMillis()))
|
||||
.setExpiration(Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)).signWith(SignatureAlgorithm.HS512, secret).compact()
|
||||
}
|
||||
|
||||
fun canTokenBeRefreshed(token: String): Boolean {
|
||||
return !isTokenExpired(token)
|
||||
}
|
||||
|
||||
fun validateToken(token: String, userDetails: UserDetails): Boolean {
|
||||
val username = getUsernameFromToken(token)
|
||||
return username == userDetails.username && !isTokenExpired(token)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val serialVersionUID = -2550185165626007488L
|
||||
const val JWT_TOKEN_VALIDITY = 5 * 60 * 60.toLong()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user