ㅇㅇ 로그인아웃 방식 변경
This commit is contained in:
parent
3dcb077e2f
commit
e39a7d1fd3
@ -22,6 +22,6 @@ COPY ${JAR_FILE} app.jar
|
||||
EXPOSE 443
|
||||
#EXPOSE 27012
|
||||
#EXPOSE 3307
|
||||
ENTRYPOINT ["java","-Dtelegram.bot.key=${BOT_KEY}","-Dtelegram.my.id=${TG_MINE}","-Dtelegram.target.id=${TG_TARGET_ID}","-Dweather.api.key=${WEATHER_KEY}","-Dspring.datasource.url=${DATASOURCE_URL}" ,"-Dspring.data.mongodb.uri=${MONGODB_HOST}","-Dspring.data.mongodb.database=${MONGODB_NAME}","-Dspring.datasource.username=${MRA_ADMIN}","-Dspring.datasource.password=${MRA_PW}","-Dresource.handler=${RESOURCE_HANDLER}","-Dresource.location=${RESOURCE_LOCATION}","-Dimage.upload.path=${IMAGE_UPLOAD_PATH}","-Dapi.gg.place=${GAPI_KEY}","-jar","app.jar"]
|
||||
#ENTRYPOINT ["java","-jar","app.jar","-Dspring-boot.run.arguments=--telegram.bot.key=${BOT_KEY}, --telegram.my.id=${TG_MINE}, --telegram.target.id=${TG_TARGET_ID}, --weather.api.key=${WEATHER_KEY}"]
|
||||
ENTRYPOINT ["java","-Dtelegram.bot.key=${BOT_KEY}","-Dtelegram.my.id=${TG_MINE}","-Dtelegram.target.id=${TG_TARGET_ID}","-Dweather.api.key=${WEATHER_KEY}","-Dspring.datasource.url=${DATASOURCE_URL}" ,"-Dspring.data.mongodb.uri=${MONGODB_HOST}","-Dspring.data.mongodb.database=${MONGODB_NAME}","-Dspring.datasource.username=${MRA_ADMIN}","-Dspring.datasource.password=${MRA_PW}","-Dresource.handler=${RESOURCE_HANDLER}","-Dresource.location=${RESOURCE_LOCATION}","-Dimage.upload.path=${IMAGE_UPLOAD_PATH}","-Dapi.gg.place=${GAPI_KEY}","-jar","app.jar"]
|
||||
#-Dtelegram.bot.key=bot7934509464:AAE_xUbICxMdywLGnxo7BkeIqA1nVza4P9w -Dtelegram.target.id=71476436 -Dtelegram.my.id=71476436 -Dweather.api.key=de574a260b1f474d99955729241909 -Dspring.datasource.url=jdbc:mariadb://mra.sbspace.synology.me -Dspring.data.mongodb.uri=mongodb://lun_admin:VioPup*383@mongo.sbspace.synology.me/?wtimeoutMS=300&connectTimeoutMS=500&socketTimeoutMS=200 -Dspring.data.mongodb.database=lun_db -Dspring.datasource.username=lun_admin -Dspring.datasource.password=VioPup*383 -Dresource.handler=/blog/post/image/** -Dresource.location=file:///imgUpload -Dimage.upload.path=imgUpload
|
||||
|
||||
@ -50,6 +50,8 @@ dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
|
||||
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
|
||||
implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity6")
|
||||
|
||||
implementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
|
||||
implementation ("org.jsoup:jsoup:1.18.1")
|
||||
|
||||
@ -104,6 +106,7 @@ tasks.withType<Test> {
|
||||
|
||||
|
||||
tasks.jar {
|
||||
archiveFileName.set("app.jar")
|
||||
manifest {
|
||||
attributes["Main-Class"] = "kr.lunaticbum.back.lun.LunApplicationKt"
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.http.CacheControl
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
import java.time.Duration
|
||||
@ -28,10 +30,13 @@ class AppConfig : WebMvcConfigurer {
|
||||
registry.addResourceHandler(resourceHandler).addResourceLocations(resourceLocation).setCacheControl(cacheControl)
|
||||
}
|
||||
|
||||
override fun addInterceptors(registry: InterceptorRegistry) {
|
||||
registry.addInterceptor(authInterceptor())
|
||||
super.addInterceptors(registry)
|
||||
}
|
||||
@Bean
|
||||
fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()
|
||||
// override fun addInterceptors(registry: InterceptorRegistry) {
|
||||
// registry.addInterceptor(authInterceptor())
|
||||
// .addPathPatterns("**/*.bs", "**/*.bjx")
|
||||
// super.addInterceptors(registry)
|
||||
// }
|
||||
|
||||
|
||||
// @Bean
|
||||
|
||||
@ -8,9 +8,9 @@ import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.ApiKeyWordKey
|
||||
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncType11
|
||||
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncTypeKey
|
||||
import kr.lunaticbum.back.lun.model.UserManager
|
||||
import kr.lunaticbum.back.lun.service.JwtService
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.lang.Nullable
|
||||
import org.springframework.security.web.authentication.RememberMeServices
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.web.servlet.HandlerInterceptor
|
||||
@ -19,12 +19,8 @@ import org.springframework.web.servlet.ModelAndView
|
||||
@Component
|
||||
class BumsInterceptor : HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
lateinit var jwtService : JwtService
|
||||
@Autowired
|
||||
lateinit var globalEvv : GlobalEnvironment
|
||||
@Autowired
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
val WRITE_PERMISSION_KEY = "PERMISSION"
|
||||
|
||||
@ -36,9 +32,13 @@ class BumsInterceptor : HandlerInterceptor {
|
||||
// println("==================== BEGIN ====================")
|
||||
// println("Request URL ===> " + request.requestURL)
|
||||
// }
|
||||
|
||||
|
||||
return super.preHandle(request, response, handler)
|
||||
}
|
||||
|
||||
// @Autowired
|
||||
// lateinit var rememberMeServices: RememberMeServices
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun postHandle(
|
||||
@ -47,68 +47,9 @@ class BumsInterceptor : HandlerInterceptor {
|
||||
handler: Any,
|
||||
@Nullable modelAndView: ModelAndView?
|
||||
) {
|
||||
var skippResourcesExtension = arrayListOf(".ajax",".js",".css","/tlg/",".api","error").filter { request.requestURI.contains(it)}.size > 0
|
||||
if (!skippResourcesExtension) {
|
||||
if (request.requestURI.contains("logout") == false && !request.cookies.isNullOrEmpty() && request.cookies.filter {
|
||||
it.name.equals(
|
||||
"access"
|
||||
) && it.value.length > 0
|
||||
}.size > 0) {
|
||||
var refreshOk = false;
|
||||
var accessOk = false;
|
||||
var access: Cookie? = null
|
||||
var refresh: Cookie? = null
|
||||
request.cookies.forEach {
|
||||
if (it.name.equals("access", true) && jwtService.validateAccessToken(it.value)) {
|
||||
access = it
|
||||
accessOk = true
|
||||
println("==================== accessOk ${accessOk} ======================")
|
||||
|
||||
}
|
||||
}
|
||||
request.cookies.forEach {
|
||||
if (it.name.equals("refresh", true) && jwtService.validateRefreshToken(access?.value, it.value)) {
|
||||
refresh = it
|
||||
refreshOk = true
|
||||
println("==================== refreshOk ${refreshOk} ======================")
|
||||
}
|
||||
}
|
||||
if (refreshOk || accessOk) {
|
||||
request.getSession(true)?.let { session ->
|
||||
session.setAttribute(WRITE_PERMISSION_KEY, true)
|
||||
session.maxInactiveInterval = 60 * 5
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
} else if (request.requestURI.contains("logout")) {
|
||||
request.getSession(true)?.let { session ->
|
||||
session.invalidate()
|
||||
session.setAttribute(WRITE_PERMISSION_KEY, false)
|
||||
}
|
||||
}
|
||||
|
||||
request.cookies?.forEach {
|
||||
if (it.name.equals("CLEAR", true)) {
|
||||
request.getSession(false)?.let { session ->
|
||||
// session.invalidate()
|
||||
session.setAttribute(WRITE_PERMISSION_KEY, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
modelAndView?.modelMap?.put(WRITE_PERMISSION_KEY,"NO")
|
||||
request.getSession(true)?.let {
|
||||
(it.getAttribute(WRITE_PERMISSION_KEY) as? Boolean)?.let { permission ->
|
||||
if (permission) {
|
||||
modelAndView?.modelMap?.put(WRITE_PERMISSION_KEY,"OK")
|
||||
modelAndView?.modelMap?.put(EncTypeKey, EncType11)
|
||||
modelAndView?.modelMap?.put(ApiKeyWordKey,"Def")
|
||||
}
|
||||
}
|
||||
}
|
||||
println("==================== END ======================")
|
||||
println("===============================================")
|
||||
}
|
||||
// if(remeberMe && authResult != null) {
|
||||
// rememberMeServices.loginSuccess(httpServletRequest, responce, authResult)
|
||||
// }
|
||||
super.postHandle(request, response, handler, modelAndView)
|
||||
}
|
||||
|
||||
|
||||
@ -18,19 +18,19 @@ class GlobalEnvironment : EnvironmentAware {
|
||||
fun padding(key : String) = pad.plus(key).plus(pad)
|
||||
}
|
||||
@Value("\${telegram.bot.key}")
|
||||
var telegramBotKey: String? = ""
|
||||
lateinit var telegramBotKey: String
|
||||
|
||||
@Value("\${telegram.my.id}")
|
||||
var telegramMyId: String? = ""
|
||||
lateinit var telegramMyId: String
|
||||
|
||||
@Value("\${telegram.target.id}")
|
||||
var telegramTargetId: String? = ""
|
||||
lateinit var telegramTargetId: String
|
||||
|
||||
@Value("\${weather.api.key}")
|
||||
var weatherApiKey: String? = ""
|
||||
lateinit var weatherApiKey: String
|
||||
|
||||
@Value("\${api.gg.place}")
|
||||
var gapiKey : String? = ""
|
||||
lateinit var gapiKey: String
|
||||
|
||||
// @Value("jwt.access-secret")
|
||||
var ACCESS_SECRET_KEY: String = "l00u00n00a00t00i00c00b00u00m00a00c00sk"
|
||||
@ -42,6 +42,7 @@ class GlobalEnvironment : EnvironmentAware {
|
||||
var REFRESH_EXPIRATION: Long = 60 * 30 * 1000L
|
||||
|
||||
override fun setEnvironment(environment: Environment) {
|
||||
environment.activeProfiles.forEach { println(it) }
|
||||
println ("telegramBotKey $telegramBotKey")
|
||||
println("telegramMyId $telegramMyId")
|
||||
println("telegramMyId $telegramTargetId")
|
||||
|
||||
@ -3,6 +3,7 @@ package kr.lunaticbum.back.lun.configs
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import kr.lunaticbum.back.lun.model.UserManager
|
||||
import kr.lunaticbum.back.lun.utils.LogService
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
@ -11,6 +12,8 @@ import org.springframework.http.HttpMethod
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
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.http.SessionCreationPolicy
|
||||
@ -24,60 +27,87 @@ import org.springframework.web.ErrorResponse
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
class SecurityConfig {
|
||||
class SecurityConfig(
|
||||
private val userManager: UserManager,
|
||||
private val bCryptPasswordEncoder: BCryptPasswordEncoder
|
||||
) {
|
||||
@Autowired
|
||||
lateinit var logService: LogService
|
||||
|
||||
|
||||
@Bean
|
||||
fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
|
||||
http.csrf {
|
||||
it.ignoringRequestMatchers("/user/joinUser.ajax").disable()
|
||||
http.csrf { csrf ->
|
||||
csrf.ignoringRequestMatchers("/user/login.bjx", "/user/joinUser.bjx") // 여기 예외 추가
|
||||
}.authorizeHttpRequests { auth ->
|
||||
auth
|
||||
.requestMatchers(
|
||||
"/", "/home",
|
||||
"/bums/where.bs" ,
|
||||
"/user/login.bs", "/user/signup.bs","/user/login.bjx",
|
||||
"/css/**", "/js/**", "/images/**", "/webjars/**", "/assets/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
}.formLogin { form ->
|
||||
form.loginPage("/user/login.bs")
|
||||
.defaultSuccessUrl("/", true)
|
||||
.permitAll()
|
||||
}.rememberMe { rememberMe ->
|
||||
rememberMe
|
||||
.key("BsTs*!12@") // 보통 안전한 키 지정
|
||||
.tokenValiditySeconds(60 * 60 * 24 * 7) // 7일간 유효
|
||||
.userDetailsService(userManager) // 사용자 정보 서비스 지정
|
||||
}.logout { logout ->
|
||||
logout.logoutUrl("/user/logout.bs").logoutSuccessUrl("/").permitAll()
|
||||
}
|
||||
http.cors { it.disable() }
|
||||
http.headers {
|
||||
it.frameOptions { frameOptionsConfig ->
|
||||
frameOptionsConfig.disable()
|
||||
}
|
||||
}
|
||||
|
||||
http.authorizeHttpRequests {
|
||||
logService.log(it.toString())
|
||||
it.requestMatchers(HttpMethod.POST,"/user/**").permitAll()
|
||||
// it.requestMatchers(HttpMethod.POST,"/user/**").permitAll()
|
||||
// it.requestMatchers(HttpMethod.POST,"/user/**").permitAll()
|
||||
// it.requestMatchers("/", "/user/**").permitAll()
|
||||
// .requestMatchers(".ajax").permitAll()
|
||||
// it.requestMatchers("/", "/user/joinUser.api").permitAll()
|
||||
// it.requestMatchers("user/joinUser.api").permitAll()
|
||||
it.requestMatchers("/blog/viewer/**").permitAll()
|
||||
it.anyRequest().permitAll()
|
||||
|
||||
// .requestMatchers("/", "/login/**").permitAll()
|
||||
|
||||
// .requestMatchers("/admins/**", "/api/v1/admins/**").hasRole(Role.ADMIN.name)
|
||||
// .anyRequest().authenticated()
|
||||
}
|
||||
http.sessionManagement {
|
||||
it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
}
|
||||
.exceptionHandling { it ->
|
||||
it.authenticationEntryPoint(unauthorizedEntryPoint)
|
||||
.accessDeniedHandler(accessDeniedHandler)
|
||||
}
|
||||
// .formLogin { formLogin ->
|
||||
// formLogin
|
||||
// .loginPage("/user/join")
|
||||
////// .usernameParameter("username")
|
||||
////// .passwordParameter("password")
|
||||
// .loginProcessingUrl("/user/joinUser.api")
|
||||
// .defaultSuccessUrl("/", true)
|
||||
// }
|
||||
|
||||
return http.build()
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun authenticationManager(http: HttpSecurity): AuthenticationManager {
|
||||
val authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder::class.java)
|
||||
authenticationManagerBuilder
|
||||
.userDetailsService(userManager)
|
||||
.passwordEncoder(bCryptPasswordEncoder)
|
||||
return authenticationManagerBuilder.build() // .and() 없이 직접 build() 호출
|
||||
}
|
||||
// @Bean
|
||||
// fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
//
|
||||
// http.csrf {
|
||||
// it.ignoringRequestMatchers("/user/joinUser.bjx").disable()
|
||||
// }
|
||||
// http.cors { it.disable() }
|
||||
// http.headers {
|
||||
// it.frameOptions { frameOptionsConfig ->
|
||||
// frameOptionsConfig.disable()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// http.authorizeHttpRequests {
|
||||
// logService.log(it.toString())
|
||||
// it.requestMatchers(HttpMethod.POST,"/user/**").permitAll()
|
||||
// it.requestMatchers("/blog/viewer/**").permitAll()
|
||||
// it.anyRequest().permitAll()
|
||||
// }
|
||||
// http.sessionManagement {
|
||||
// it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
// }
|
||||
// .exceptionHandling { it ->
|
||||
// it.authenticationEntryPoint(unauthorizedEntryPoint)
|
||||
// .accessDeniedHandler(accessDeniedHandler)
|
||||
// }
|
||||
//// .formLogin { formLogin ->
|
||||
//// formLogin
|
||||
//// .loginPage("/user/join")
|
||||
//////// .usernameParameter("username")
|
||||
//////// .passwordParameter("password")
|
||||
//// .loginProcessingUrl("/user/joinUser.api")
|
||||
//// .defaultSuccessUrl("/", true)
|
||||
//// }
|
||||
//
|
||||
// return http.build()
|
||||
// }
|
||||
|
||||
private val unauthorizedEntryPoint =
|
||||
AuthenticationEntryPoint { request: HttpServletRequest?, response: HttpServletResponse, authException: AuthenticationException? ->
|
||||
val fail: ErrorResponse = ErrorResponse.create( Throwable("아직 못들어와"),
|
||||
|
||||
@ -13,7 +13,6 @@ import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.ApiKeyWordKey
|
||||
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncType11
|
||||
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncTypeKey
|
||||
import kr.lunaticbum.back.lun.model.*
|
||||
import kr.lunaticbum.back.lun.service.JwtService
|
||||
import kr.lunaticbum.back.lun.utils.LogService
|
||||
import kr.lunaticbum.back.lun.utils.getFileExtension
|
||||
import net.coobird.thumbnailator.Thumbnails
|
||||
@ -28,6 +27,8 @@ import org.springframework.core.io.Resource
|
||||
import org.springframework.core.io.UrlResource
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import org.springframework.web.multipart.MultipartFile
|
||||
import org.springframework.web.reactive.function.client.WebClient
|
||||
@ -55,7 +56,7 @@ class BlogController() {
|
||||
@Autowired
|
||||
lateinit var logService: LogService
|
||||
val WRITE_PERMISSION_KEY = "PERMISSION"
|
||||
@GetMapping("write/{token}","write")
|
||||
@GetMapping("write/{token}","write.bs")
|
||||
fun writ(@PathVariable token : String? ) : ResultMV{
|
||||
val vm = ResultMV("content/blog/write")
|
||||
if (token.equals(TEMPTOKEN)) {
|
||||
@ -67,17 +68,10 @@ class BlogController() {
|
||||
} else {
|
||||
vm.modelMap.put(WRITE_PERMISSION_KEY,"NO")
|
||||
}
|
||||
// when(System.currentTimeMillis() % 5L) {
|
||||
// 0L -> vm.modelMap.put(EncTypeKey,"T4")
|
||||
// 1L -> vm.modelMap.put(EncTypeKey,"T3")
|
||||
// 2L -> vm.modelMap.put(EncTypeKey,"T2")
|
||||
// else -> vm.modelMap.put(EncTypeKey,"T0")
|
||||
// }
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
@PostMapping("post.ajax")
|
||||
@PostMapping("post.bjx")
|
||||
fun post(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : ResponseEntity<ResponceResult> {
|
||||
logService.log(httpServletRequest.requestURI)
|
||||
logService.log(jsonString)
|
||||
@ -164,16 +158,16 @@ class BlogController() {
|
||||
return vm
|
||||
}
|
||||
|
||||
@Autowired
|
||||
lateinit var jwtService : JwtService
|
||||
|
||||
@GetMapping("modify")
|
||||
@GetMapping("modify.bs")
|
||||
fun modify(httpServletRequest: HttpServletRequest, @RequestParam("token") token : String?) : ResultMV{
|
||||
logService.log("incoming modify")
|
||||
val vm = ResultMV("content/blog/modify")
|
||||
vm.modelMap.put(WRITE_PERMISSION_KEY,"NO")
|
||||
httpServletRequest.getSession(true)?.let { session ->
|
||||
(session.getAttribute(WRITE_PERMISSION_KEY) as? Boolean)?.let {
|
||||
val authentication = SecurityContextHolder.getContext().authentication
|
||||
val principal = authentication.principal
|
||||
if (principal is UserDetails) {
|
||||
val username = principal.username
|
||||
// 추가 정보 사용 가능
|
||||
postManageg.find20()?.apply {
|
||||
forEach {
|
||||
it.title = URLDecoder.decode(it.title)
|
||||
@ -186,7 +180,6 @@ class BlogController() {
|
||||
vm.modelMap.put("path","editor/")
|
||||
vm.modelMap.put("SK",token)
|
||||
}
|
||||
}
|
||||
vm.modelMap.put("rowKey","chunkedPosts_")
|
||||
return vm
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ class BumsPrivate {
|
||||
@Autowired
|
||||
lateinit var locationService: LocationLogService
|
||||
|
||||
@GetMapping("where")
|
||||
@GetMapping("where.bs")
|
||||
fun where() : ResultMV {
|
||||
val m = ResultMV("content/private/where")
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncType11
|
||||
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncTypeKey
|
||||
import kr.lunaticbum.back.lun.configs.JwtRule
|
||||
import kr.lunaticbum.back.lun.model.*
|
||||
import kr.lunaticbum.back.lun.service.JwtService
|
||||
import kr.lunaticbum.back.lun.utils.JwtUtil
|
||||
import kr.lunaticbum.back.lun.utils.LogService
|
||||
import kr.lunaticbum.back.lun.utils.extractModelData
|
||||
@ -17,12 +16,18 @@ import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.ResponseCookie
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import org.springframework.web.reactive.function.client.WebClient
|
||||
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.web.authentication.RememberMeServices
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import javax.naming.AuthenticationException
|
||||
|
||||
|
||||
@RestController
|
||||
@ -38,10 +43,8 @@ class UserController {
|
||||
|
||||
@Autowired
|
||||
lateinit var userManager: UserManager
|
||||
@Autowired
|
||||
lateinit var jwtService : JwtService
|
||||
|
||||
@GetMapping("join")
|
||||
@GetMapping("join.bs")
|
||||
fun hello(httpServletRequest: HttpServletRequest): ResultMV {
|
||||
logService.log("onJoin")
|
||||
val vm = ResultMV("content/user/join")
|
||||
@ -60,7 +63,7 @@ class UserController {
|
||||
return vm
|
||||
}
|
||||
|
||||
@GetMapping("login")
|
||||
@GetMapping("login.bs")
|
||||
fun userLogin(httpServletRequest: HttpServletRequest): ResultMV {
|
||||
logService.log("onJoin")
|
||||
val vm = ResultMV("content/user/login")
|
||||
@ -69,9 +72,18 @@ class UserController {
|
||||
return vm
|
||||
}
|
||||
|
||||
// @GetMapping("logout.bs")
|
||||
// fun logoutBs(session: HttpSession): ResultMV {
|
||||
// session.invalidate(); // 세션 날리기 (로그아웃)
|
||||
// return "redirect:/"; // 홈으로 이동
|
||||
// }
|
||||
|
||||
@Autowired
|
||||
lateinit var authenticationManager: AuthenticationManager
|
||||
|
||||
|
||||
@ResponseBody
|
||||
@PostMapping("login.ajax")
|
||||
@PostMapping("login.bjx")
|
||||
fun login(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : ResponseEntity<LoginResult> {
|
||||
try {
|
||||
|
||||
@ -82,24 +94,37 @@ class UserController {
|
||||
var u : UserDetails? = null
|
||||
var user : User? = null
|
||||
var tokenData : TokenData? = null
|
||||
var remeberMe = false
|
||||
var authResult : Authentication? = null
|
||||
jsonString.extractModelData { exception, originDataString ->
|
||||
if (exception == null) {
|
||||
logService.log(originDataString)
|
||||
logService.log("originDataString >>> $originDataString")
|
||||
val target = Gson().fromJson(originDataString, User::class.java) ?: User()
|
||||
user = userManager.findById(target.user_id?.trim() ?: "")?.block()
|
||||
if (user == null && ((target.user_id?.trim()?.length ?: 0) > 3 == true)) {
|
||||
user = userManager.findByEmail(target.user_id?.trim() ?: "")?.block()
|
||||
}
|
||||
if (user != null) {
|
||||
if(userManager.isCorrectUser(user!!,target.user_pw!!)){
|
||||
tokenData = jwtService.generate(user!!)
|
||||
try {
|
||||
val authToken = UsernamePasswordAuthenticationToken(target.user_id, target.user_pw)
|
||||
authResult = authenticationManager.authenticate(authToken) // 인증 시도
|
||||
println("authResult >>>> $authResult")
|
||||
// 인증 성공 시 SecurityContextHolder에 인증 정보 저장
|
||||
SecurityContextHolder.getContext().authentication = authResult
|
||||
|
||||
// 인증 정보가 담긴 SecurityContext를 세션에 저장
|
||||
val session = httpServletRequest.getSession(true)
|
||||
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext())
|
||||
println("authResult >>>> LOGIN OK")
|
||||
|
||||
val principal = authResult?.principal
|
||||
if (principal is UserDetails) {
|
||||
val username = principal.username
|
||||
|
||||
val session = httpServletRequest.getSession(true)
|
||||
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext())
|
||||
remeberMe = target.remeberMe ?: false
|
||||
} else {
|
||||
lResultMsg = "is wrong infomation id or passord"
|
||||
lResultCode = 7100
|
||||
}
|
||||
} else {
|
||||
lResultMsg = "not founding user[can't find same id,email.. ]"
|
||||
lResultCode = 7100
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} else {
|
||||
exception.printStackTrace()
|
||||
@ -117,7 +142,6 @@ class UserController {
|
||||
this.refresh = setTokenToCookie(JwtRule.REFRESH_PREFIX.value, tokenData?.refreshToken ?: "", globalEvv.REFRESH_EXPIRATION / 1000).toString().replace("refresh=","")
|
||||
}).apply {
|
||||
|
||||
|
||||
}
|
||||
|
||||
return responce
|
||||
@ -149,7 +173,7 @@ class UserController {
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@PostMapping("logout.ajax")
|
||||
@PostMapping("logout.bjx")
|
||||
fun logout(httpServletRequest: HttpServletRequest) : ResponseEntity<ResponceResult> {
|
||||
val responce = ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(ResponceResult().apply {
|
||||
|
||||
@ -158,7 +182,7 @@ class UserController {
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@PostMapping("joinUser.ajax")
|
||||
@PostMapping("joinUser.bjx")
|
||||
fun joinUser(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : ResponseEntity<ResponceResult> {
|
||||
logService.log("${httpServletRequest.requestURI}")
|
||||
logService.log(jsonString)
|
||||
@ -174,9 +198,6 @@ class UserController {
|
||||
}else if (userManager.findById(user!!.user_id!!)?.block() != null) {
|
||||
lResultCode = 7001
|
||||
lResultMsg = "user insert Fail Reason : already has Same Id"
|
||||
}else if (userManager.findByEmail(user!!.user_email!!)?.block() != null ) {
|
||||
lResultCode = 7002
|
||||
lResultMsg = "user insert Fail Reason : already has Same Email"
|
||||
} else {
|
||||
u = userManager.save(user).block()
|
||||
}
|
||||
|
||||
@ -39,10 +39,12 @@ class User {
|
||||
@CreatedDate
|
||||
var user_join: Long = 0L
|
||||
|
||||
var user_name: String? = null
|
||||
// var user_name: String? = null
|
||||
var isAccept : String? = null
|
||||
var isAdmin : String? = null
|
||||
|
||||
var remeberMe : Boolean? = false
|
||||
|
||||
fun checkValid() : Boolean {
|
||||
if (
|
||||
((user_id?.length ?: 0) > 5) &&
|
||||
@ -111,8 +113,8 @@ interface UserRepository : ReactiveMongoRepository<User, String> {
|
||||
@Query("{user_id :?0}")
|
||||
override fun findById(user_id: String): Mono<User>
|
||||
|
||||
@Query("{user_email :?0}")
|
||||
fun findByEmail(user_email: String): Mono<User>
|
||||
// @Query("{user_email :?0}")
|
||||
// fun findByEmail(user_email: String): Mono<User>
|
||||
|
||||
|
||||
fun save(user: User): Mono<User>
|
||||
@ -123,23 +125,24 @@ enum class UserRole {
|
||||
}
|
||||
interface UserService {
|
||||
fun findById(id: String): Mono<User>?
|
||||
fun findByEmail(id: String): Mono<User>?
|
||||
// fun findByEmail(id: String): Mono<User>?
|
||||
}
|
||||
|
||||
@Service
|
||||
class UserManager : UserService , UserDetailsService {
|
||||
class UserManager(
|
||||
private val passwordEncoder: PasswordEncoder
|
||||
) : UserService , UserDetailsService {
|
||||
@Autowired
|
||||
private lateinit var logService: LogService
|
||||
|
||||
@Autowired
|
||||
private lateinit var userRepository: UserRepository
|
||||
|
||||
@Autowired
|
||||
private lateinit var bCryptPasswordEncoder: PasswordEncoder
|
||||
|
||||
override fun findByEmail(id: String): Mono<User>? {
|
||||
return userRepository.findByEmail(id)
|
||||
}
|
||||
|
||||
// override fun findByEmail(id: String): Mono<User>? {
|
||||
// return userRepository.findByEmail(id)
|
||||
// }
|
||||
|
||||
override fun findById(id: String): Mono<User>? {
|
||||
return userRepository.findById(id)
|
||||
@ -149,19 +152,22 @@ class UserManager : UserService , UserDetailsService {
|
||||
|
||||
fun save(user: User): Mono<User> {
|
||||
println("saved user before ${user}")
|
||||
user.hashPassword(bCryptPasswordEncoder)
|
||||
user.hashPassword(passwordEncoder)
|
||||
return userRepository.save(user)
|
||||
}
|
||||
|
||||
fun isCorrectUser(user: User, password : String) : Boolean {
|
||||
return user.checkPassword(password,bCryptPasswordEncoder)
|
||||
return user.checkPassword(password,passwordEncoder)
|
||||
}
|
||||
|
||||
|
||||
override fun loadUserByUsername(username: String?): UserDetails {
|
||||
var user = findById(username!!)?.blockOptional(Duration.ofMillis(5000L))?.get() ?: User()
|
||||
logService.log("username ${username}")
|
||||
user.hashPassword(bCryptPasswordEncoder)
|
||||
return org.springframework.security.core.userdetails.User.builder().username(user.user_id ?: "").password(user.user_pw).roles(if ("Y".equals(user.isAdmin)) Role.ADMIN.name else {Role.USER.name}).build()
|
||||
var user = findById(username!!)?.blockOptional(Duration.ofMillis(5000L))?.get() ?: User()
|
||||
// user.hashPassword(passwordEncoder)
|
||||
return org.springframework.security.core.userdetails.User.builder()
|
||||
.username(user.user_id ?: "")
|
||||
.password(user.user_pw)
|
||||
.roles(if ("Y".equals(user.isAdmin)) Role.ADMIN.name else {Role.USER.name}).build()
|
||||
}
|
||||
}
|
||||
@ -1,185 +1,185 @@
|
||||
package kr.lunaticbum.back.lun.service
|
||||
|
||||
import io.jsonwebtoken.Claims
|
||||
import io.jsonwebtoken.Jws
|
||||
import io.jsonwebtoken.Jwts
|
||||
import jakarta.servlet.http.Cookie
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import kr.lunaticbum.back.lun.configs.GlobalEnvironment
|
||||
import kr.lunaticbum.back.lun.configs.JwtGenerator
|
||||
import kr.lunaticbum.back.lun.configs.JwtRule
|
||||
import kr.lunaticbum.back.lun.configs.TokenStatus
|
||||
import kr.lunaticbum.back.lun.model.*
|
||||
import kr.lunaticbum.back.lun.utils.BusinessException
|
||||
import kr.lunaticbum.back.lun.utils.ErrorCode
|
||||
import kr.lunaticbum.back.lun.utils.JwtUtil
|
||||
import lombok.extern.slf4j.Slf4j
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.ResponseCookie
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.token.Token
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.security.Key
|
||||
import java.time.Duration
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
|
||||
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
@Slf4j
|
||||
class JwtService {
|
||||
|
||||
@Autowired
|
||||
lateinit var globalEvv : GlobalEnvironment
|
||||
|
||||
@Autowired
|
||||
private lateinit var jwtGenerator: JwtGenerator
|
||||
|
||||
@Autowired
|
||||
private lateinit var jwtUtil: JwtUtil
|
||||
|
||||
|
||||
@Autowired
|
||||
private lateinit var customUserDetailsService: UserManager
|
||||
|
||||
@Autowired
|
||||
private lateinit var tokenRepository : TokenDataRepository
|
||||
|
||||
// private val ACCESS_SECRET_KEY: Key = jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY)
|
||||
// private val REFRESH_SECRET_KEY: Key = jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY)
|
||||
|
||||
fun validateUser(requestUser: User) {
|
||||
if (requestUser.getRole() === UserRole.NOT_REGISTERED) {
|
||||
throw BusinessException(ErrorCode.NOT_AUTHENTICATED_USER)
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun generate(requestUser: User): TokenData? {
|
||||
var accessToken = jwtGenerator.generateAccessToken(jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY), globalEvv.ACCESS_EXPIRATION, requestUser)
|
||||
var refreshToken = jwtGenerator.generateRefreshToken(jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY), globalEvv.REFRESH_EXPIRATION, requestUser)
|
||||
var token = TokenData(accessToken, refreshToken)
|
||||
return tokenRepository.save(token).block()
|
||||
}
|
||||
|
||||
|
||||
private fun setTokenToCookie(tokenPrefix: String, token: String, maxAgeSeconds: Long): ResponseCookie {
|
||||
return ResponseCookie.from(tokenPrefix, token)
|
||||
.path("/")
|
||||
.maxAge(maxAgeSeconds)
|
||||
.httpOnly(true)
|
||||
.sameSite("None")
|
||||
.secure(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun validateAccessToken(token: String?): Boolean {
|
||||
return jwtUtil.getTokenStatus(token, jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY)) == TokenStatus.AUTHENTICATED
|
||||
}
|
||||
|
||||
fun validateRefreshToken(token: String?, refreshToken: String?): Boolean {
|
||||
try {
|
||||
val isRefreshValid = jwtUtil.getTokenStatus(refreshToken, jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY)) == TokenStatus.AUTHENTICATED
|
||||
val storedToken: TokenData? = tokenRepository.findBytokenKey(token ?: "").block(Duration.ofSeconds(10))
|
||||
val isTokenMatched: Boolean = storedToken?.refreshToken.equals(refreshToken)
|
||||
return isRefreshValid && isTokenMatched
|
||||
} catch (e :Exception){
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun resolveTokenFromCookie(request: HttpServletRequest, tokenPrefix: JwtRule?): String {
|
||||
val cookies = request.cookies ?: throw BusinessException(ErrorCode.JWT_TOKEN_NOT_FOUND)
|
||||
return jwtUtil.resolveTokenFromCookie(cookies, tokenPrefix!!)
|
||||
}
|
||||
|
||||
fun getAuthentication(token: String): Authentication {
|
||||
val principal: UserDetails = customUserDetailsService.loadUserByUsername(getUserPk(token, jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY)))
|
||||
return UsernamePasswordAuthenticationToken(principal, "", principal.authorities)
|
||||
}
|
||||
|
||||
private fun getUserPk(token: String, secretKey: Key): String {
|
||||
return Jwts.parserBuilder()
|
||||
.setSigningKey(secretKey)
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody()
|
||||
.getSubject()
|
||||
}
|
||||
|
||||
fun getIdentifierFromRefresh(refreshToken: String?): String {
|
||||
try {
|
||||
return Jwts.parserBuilder()
|
||||
.setSigningKey(jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY))
|
||||
.build()
|
||||
.parseClaimsJws(refreshToken)
|
||||
.getBody()
|
||||
.getSubject()
|
||||
} catch (e: Exception) {
|
||||
throw BusinessException(ErrorCode.INVALID_JWT)
|
||||
}
|
||||
}
|
||||
|
||||
fun logout(token: String, response: HttpServletResponse) {
|
||||
tokenRepository.deleteBytokenKey(token)
|
||||
|
||||
val accessCookie = jwtUtil.resetToken(JwtRule.ACCESS_PREFIX)
|
||||
val refreshCookie = jwtUtil.resetToken(JwtRule.REFRESH_PREFIX)
|
||||
|
||||
response.addCookie(accessCookie)
|
||||
response.addCookie(refreshCookie)
|
||||
}
|
||||
fun getUserIdFromToken(token: String?): String? {
|
||||
try {
|
||||
return jwtUtil.extractToken(token,jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY))?.body?.get("Identifier")
|
||||
.toString()
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
fun getUserIdFromRefresh(token: String?): String? {
|
||||
try {
|
||||
return jwtUtil.extractToken(token,jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY))?.body?.get("Identifier")
|
||||
.toString()
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun hasPerrmission(request: HttpServletRequest): Boolean {
|
||||
var correctUserCheck = -1;
|
||||
if (request.requestURI.contains("logout") == false && !request.cookies.isNullOrEmpty() && request.cookies.filter { it.name.equals("access") && it.value.length > 0 }.size > 0) {
|
||||
var access : Cookie?= null
|
||||
var refresh : Cookie?= null
|
||||
request.cookies.forEach {
|
||||
if (it.name.equals("access", true) && validateAccessToken(it.value)){
|
||||
access = it
|
||||
correctUserCheck += 1
|
||||
}
|
||||
}
|
||||
request.cookies.forEach {
|
||||
if (it.name.equals("refresh", true) && validateRefreshToken(access?.value,it.value)){
|
||||
refresh = it
|
||||
correctUserCheck += 1
|
||||
}
|
||||
}
|
||||
if (correctUserCheck > 0) {
|
||||
println("Response correctUserCheck ===> ${correctUserCheck}")
|
||||
} else {
|
||||
println("Response correctUserCheck ===> ${correctUserCheck}")
|
||||
}
|
||||
} else if (request.requestURI.contains("logout")) {
|
||||
|
||||
}
|
||||
return correctUserCheck > 0
|
||||
}
|
||||
}
|
||||
//package kr.lunaticbum.back.lun.service
|
||||
//
|
||||
//import io.jsonwebtoken.Claims
|
||||
//import io.jsonwebtoken.Jws
|
||||
//import io.jsonwebtoken.Jwts
|
||||
//import jakarta.servlet.http.Cookie
|
||||
//import jakarta.servlet.http.HttpServletRequest
|
||||
//import jakarta.servlet.http.HttpServletResponse
|
||||
//import kr.lunaticbum.back.lun.configs.GlobalEnvironment
|
||||
//import kr.lunaticbum.back.lun.configs.JwtGenerator
|
||||
//import kr.lunaticbum.back.lun.configs.JwtRule
|
||||
//import kr.lunaticbum.back.lun.configs.TokenStatus
|
||||
//import kr.lunaticbum.back.lun.model.*
|
||||
//import kr.lunaticbum.back.lun.utils.BusinessException
|
||||
//import kr.lunaticbum.back.lun.utils.ErrorCode
|
||||
//import kr.lunaticbum.back.lun.utils.JwtUtil
|
||||
//import lombok.extern.slf4j.Slf4j
|
||||
//import org.springframework.beans.factory.annotation.Autowired
|
||||
//import org.springframework.http.HttpHeaders
|
||||
//import org.springframework.http.ResponseCookie
|
||||
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
//import org.springframework.security.core.Authentication
|
||||
//import org.springframework.security.core.token.Token
|
||||
//import org.springframework.security.core.userdetails.UserDetails
|
||||
//import org.springframework.stereotype.Service
|
||||
//import org.springframework.transaction.annotation.Transactional
|
||||
//import java.security.Key
|
||||
//import java.time.Duration
|
||||
//import java.util.*
|
||||
//import java.util.function.Consumer
|
||||
//
|
||||
//
|
||||
//@Service
|
||||
//@Transactional(readOnly = true)
|
||||
//@Slf4j
|
||||
//class JwtService {
|
||||
//
|
||||
// @Autowired
|
||||
// lateinit var globalEvv : GlobalEnvironment
|
||||
//
|
||||
// @Autowired
|
||||
// private lateinit var jwtGenerator: JwtGenerator
|
||||
//
|
||||
// @Autowired
|
||||
// private lateinit var jwtUtil: JwtUtil
|
||||
//
|
||||
//
|
||||
// @Autowired
|
||||
// private lateinit var customUserDetailsService: UserManager
|
||||
//
|
||||
// @Autowired
|
||||
// private lateinit var tokenRepository : TokenDataRepository
|
||||
//
|
||||
//// private val ACCESS_SECRET_KEY: Key = jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY)
|
||||
//// private val REFRESH_SECRET_KEY: Key = jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY)
|
||||
//
|
||||
// fun validateUser(requestUser: User) {
|
||||
// if (requestUser.getRole() === UserRole.NOT_REGISTERED) {
|
||||
// throw BusinessException(ErrorCode.NOT_AUTHENTICATED_USER)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Transactional
|
||||
// fun generate(requestUser: User): TokenData? {
|
||||
// var accessToken = jwtGenerator.generateAccessToken(jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY), globalEvv.ACCESS_EXPIRATION, requestUser)
|
||||
// var refreshToken = jwtGenerator.generateRefreshToken(jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY), globalEvv.REFRESH_EXPIRATION, requestUser)
|
||||
// var token = TokenData(accessToken, refreshToken)
|
||||
// return tokenRepository.save(token).block()
|
||||
// }
|
||||
//
|
||||
//
|
||||
// private fun setTokenToCookie(tokenPrefix: String, token: String, maxAgeSeconds: Long): ResponseCookie {
|
||||
// return ResponseCookie.from(tokenPrefix, token)
|
||||
// .path("/")
|
||||
// .maxAge(maxAgeSeconds)
|
||||
// .httpOnly(true)
|
||||
// .sameSite("None")
|
||||
// .secure(true)
|
||||
// .build()
|
||||
// }
|
||||
//
|
||||
// fun validateAccessToken(token: String?): Boolean {
|
||||
// return jwtUtil.getTokenStatus(token, jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY)) == TokenStatus.AUTHENTICATED
|
||||
// }
|
||||
//
|
||||
// fun validateRefreshToken(token: String?, refreshToken: String?): Boolean {
|
||||
// try {
|
||||
// val isRefreshValid = jwtUtil.getTokenStatus(refreshToken, jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY)) == TokenStatus.AUTHENTICATED
|
||||
// val storedToken: TokenData? = tokenRepository.findBytokenKey(token ?: "").block(Duration.ofSeconds(10))
|
||||
// val isTokenMatched: Boolean = storedToken?.refreshToken.equals(refreshToken)
|
||||
// return isRefreshValid && isTokenMatched
|
||||
// } catch (e :Exception){
|
||||
//
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// fun resolveTokenFromCookie(request: HttpServletRequest, tokenPrefix: JwtRule?): String {
|
||||
// val cookies = request.cookies ?: throw BusinessException(ErrorCode.JWT_TOKEN_NOT_FOUND)
|
||||
// return jwtUtil.resolveTokenFromCookie(cookies, tokenPrefix!!)
|
||||
// }
|
||||
//
|
||||
// fun getAuthentication(token: String): Authentication {
|
||||
// val principal: UserDetails = customUserDetailsService.loadUserByUsername(getUserPk(token, jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY)))
|
||||
// return UsernamePasswordAuthenticationToken(principal, "", principal.authorities)
|
||||
// }
|
||||
//
|
||||
// private fun getUserPk(token: String, secretKey: Key): String {
|
||||
// return Jwts.parserBuilder()
|
||||
// .setSigningKey(secretKey)
|
||||
// .build()
|
||||
// .parseClaimsJws(token)
|
||||
// .getBody()
|
||||
// .getSubject()
|
||||
// }
|
||||
//
|
||||
// fun getIdentifierFromRefresh(refreshToken: String?): String {
|
||||
// try {
|
||||
// return Jwts.parserBuilder()
|
||||
// .setSigningKey(jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY))
|
||||
// .build()
|
||||
// .parseClaimsJws(refreshToken)
|
||||
// .getBody()
|
||||
// .getSubject()
|
||||
// } catch (e: Exception) {
|
||||
// throw BusinessException(ErrorCode.INVALID_JWT)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun logout(token: String, response: HttpServletResponse) {
|
||||
// tokenRepository.deleteBytokenKey(token)
|
||||
//
|
||||
// val accessCookie = jwtUtil.resetToken(JwtRule.ACCESS_PREFIX)
|
||||
// val refreshCookie = jwtUtil.resetToken(JwtRule.REFRESH_PREFIX)
|
||||
//
|
||||
// response.addCookie(accessCookie)
|
||||
// response.addCookie(refreshCookie)
|
||||
// }
|
||||
// fun getUserIdFromToken(token: String?): String? {
|
||||
// try {
|
||||
// return jwtUtil.extractToken(token,jwtUtil.getSigningKey(globalEvv.ACCESS_SECRET_KEY))?.body?.get("Identifier")
|
||||
// .toString()
|
||||
// } catch (e: Exception) {
|
||||
// return null
|
||||
// }
|
||||
// }
|
||||
// fun getUserIdFromRefresh(token: String?): String? {
|
||||
// try {
|
||||
// return jwtUtil.extractToken(token,jwtUtil.getSigningKey(globalEvv.REFRESH_SECRET_KEY))?.body?.get("Identifier")
|
||||
// .toString()
|
||||
// } catch (e: Exception) {
|
||||
// return null
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// fun hasPerrmission(request: HttpServletRequest): Boolean {
|
||||
// var correctUserCheck = -1;
|
||||
// if (request.requestURI.contains("logout") == false && !request.cookies.isNullOrEmpty() && request.cookies.filter { it.name.equals("access") && it.value.length > 0 }.size > 0) {
|
||||
// var access : Cookie?= null
|
||||
// var refresh : Cookie?= null
|
||||
// request.cookies.forEach {
|
||||
// if (it.name.equals("access", true) && validateAccessToken(it.value)){
|
||||
// access = it
|
||||
// correctUserCheck += 1
|
||||
// }
|
||||
// }
|
||||
// request.cookies.forEach {
|
||||
// if (it.name.equals("refresh", true) && validateRefreshToken(access?.value,it.value)){
|
||||
// refresh = it
|
||||
// correctUserCheck += 1
|
||||
// }
|
||||
// }
|
||||
// if (correctUserCheck > 0) {
|
||||
// println("Response correctUserCheck ===> ${correctUserCheck}")
|
||||
// } else {
|
||||
// println("Response correctUserCheck ===> ${correctUserCheck}")
|
||||
// }
|
||||
// } else if (request.requestURI.contains("logout")) {
|
||||
//
|
||||
// }
|
||||
// return correctUserCheck > 0
|
||||
// }
|
||||
//}
|
||||
@ -65,6 +65,7 @@ fun String.extractModelData(calback : (Exception?,String)->Unit) {
|
||||
Gson().fromJson<RequestModel>(resultString, RequestModel::class.java).let { model ->
|
||||
model.data?.let { jsonString ->
|
||||
try {
|
||||
println("RequestModel ${jsonString}")
|
||||
calback.invoke(null,model.extractData())
|
||||
} catch (e: Exception) {
|
||||
calback.invoke(ExtractDataRequestModelException("Exception on extractData with ${Gson().toJson(model)}", e.cause), jsonString)
|
||||
|
||||
@ -86,6 +86,8 @@ spring.ai.vectorstore.qdrant.collection-name=blama_vectors
|
||||
|
||||
spring.ai.ollama.embedding.enabled=true
|
||||
|
||||
|
||||
resource.handler=.
|
||||
resource.location=.
|
||||
server.forward-headers-strategy=framework
|
||||
#>>>>>>> ab915d0a416c69708f1df1ad76d7a14c779c1f59
|
||||
|
||||
|
||||
@ -168,3 +168,31 @@ footer {
|
||||
min-height: 5vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#rememberMe {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: lightblue; /* 체크박스 배경색 */
|
||||
border: 2px solid blue; /* 테두리 색 */
|
||||
appearance: none; /* 기본 OS 스타일 제거 */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#rememberMe:checked {
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
#rememberMe:checked::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 7px;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
@ -31,7 +31,7 @@ function onclickWrite(type, keyword, html) {
|
||||
baseData.firstPostLat = encodeURIComponent(currentLat)
|
||||
baseData.firstPostLon = encodeURIComponent(currentLon)
|
||||
}
|
||||
let uploadUrl = getMainPath() + "/blog/post.ajax";
|
||||
let uploadUrl = getMainPath() + "/blog/post.bjx";
|
||||
if(confirm(JSON.stringify(baseData) + "\n해당 내용으로\n유저 등록 하실??")) {
|
||||
post(uploadUrl,type,JSON.stringify(baseData),keyword, function (resultData) {
|
||||
alert(resultData)
|
||||
|
||||
@ -147,7 +147,7 @@ function postLogin(target,type, data, key,callBackResult) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
httpRequest.withCredentials = true
|
||||
httpRequest.open('POST', target, true);
|
||||
httpRequest.setRequestHeader("Content-Type", "text/plain");
|
||||
var odd = []
|
||||
@ -172,15 +172,15 @@ function mainPath() {
|
||||
}
|
||||
|
||||
function gotoWrite() {
|
||||
document.location.replace(getMainPath()+"/blog/write")
|
||||
document.location.replace(getMainPath()+"/blog/write.bs")
|
||||
}
|
||||
|
||||
function gotoModify() {
|
||||
document.location.replace(getMainPath()+"/blog/modify")
|
||||
document.location.replace(getMainPath()+"/blog/modify.bs")
|
||||
}
|
||||
|
||||
function gotoWhere() {
|
||||
document.location.replace(getMainPath()+"/bums/where")
|
||||
document.location.replace(getMainPath()+"/bums/where.bs")
|
||||
}
|
||||
|
||||
function logout() {
|
||||
@ -191,21 +191,35 @@ function logout() {
|
||||
console.log(document.cookie["JSESSIONID"])
|
||||
document.cookie = "JSESSIONID=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"
|
||||
document.cookie = "CLEAR="+Date.now()+"";
|
||||
let logOutUrl = getMainPath() + "/user/logout.ajax";
|
||||
post(logOutUrl,"","","", function (resultData) {
|
||||
alert("로그아웃 됨요~! 빠염~!")
|
||||
document.location.replace(document.location)
|
||||
})
|
||||
let logOutUrl = getMainPath() + "/user/logout.bs";
|
||||
|
||||
alert("로그아웃 됨요~! 빠염~!")
|
||||
|
||||
// 동적으로 form 생성하여 POST 요청 전송
|
||||
const form = document.createElement('form');
|
||||
form.method = 'POST';
|
||||
form.action = getMainPath() + '/user/logout.bs';
|
||||
|
||||
// CSRF 토큰을 meta태그 등에서 얻어서 삽입 (예: <meta name="_csrf" content="토큰값">)
|
||||
const csrfToken = document.querySelector('meta[name="_csrf"]').getAttribute('content');
|
||||
const csrfParam = document.querySelector('meta[name="_csrf_parameter"]').getAttribute('content');
|
||||
const csrfInput = document.createElement('input');
|
||||
csrfInput.type = 'hidden';
|
||||
csrfInput.name = csrfParam; // 예: "_csrf"
|
||||
csrfInput.value = csrfToken;
|
||||
form.appendChild(csrfInput);
|
||||
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function gotoLogin() {
|
||||
console.log(`location.port >> ${location.port}`)
|
||||
location.href = getMainPath()+"/login"
|
||||
location.href = getMainPath()+"/login.bs"
|
||||
}
|
||||
|
||||
function gotoJoin() {
|
||||
document.location.replace(getMainPath() + "/user/join")
|
||||
document.location.replace(getMainPath() + "/user/join.bs")
|
||||
}
|
||||
|
||||
function goToView(path,id) {
|
||||
@ -218,7 +232,7 @@ function onclickLogin(type, keyword) {
|
||||
'user_id': user_id.value,
|
||||
'user_pw': user_pw.value,
|
||||
}
|
||||
postLogin(getMainPath()+"/user/login.ajax",type,JSON.stringify(data),keyword, function (data) {
|
||||
postLogin(getMainPath()+"/user/login.bjx",type,JSON.stringify(data),keyword, function (data) {
|
||||
if (data.isOk) {
|
||||
|
||||
document.cookie = "access=" + data.token.split(";")[0]+";"
|
||||
@ -229,7 +243,7 @@ function onclickLogin(type, keyword) {
|
||||
} else {
|
||||
if (data.resultCode === 7100) {
|
||||
if(confirm(`너 누구임 정보 없는데?!\n${data.resultMsg}[${data.resultCode}]\n가입 할래!?`)){
|
||||
document.location.replace(getMainPath() + "/user/join")
|
||||
document.location.replace(getMainPath() + "/user/join.bs")
|
||||
}
|
||||
} else {
|
||||
alert(`너 누구임?!\n${data.resultMsg}[${data.resultCode}]`)
|
||||
@ -320,11 +334,13 @@ function submitLoginForm() {
|
||||
// const password = document.getElementById('loginPassword').value;
|
||||
let user_id = document.getElementById('loginId')
|
||||
let user_pw = document.getElementById('loginPassword')
|
||||
let rememberMe = document.getElementById('rememberMe')
|
||||
let data = {
|
||||
'user_id': user_id.value,
|
||||
'user_pw': user_pw.value,
|
||||
'rememberMe' : rememberMe.value,
|
||||
}
|
||||
postLogin(getMainPath()+"/user/login.ajax",user_pw.data,JSON.stringify(data),user_pw.data, function (data) {
|
||||
postLogin(getMainPath()+"/user/login.bjx",user_pw.data,JSON.stringify(data),user_pw.data, function (data) {
|
||||
closePopup()
|
||||
if (data.isOk) {
|
||||
document.cookie = "access=" + data.token.split(";")[0]+";"
|
||||
|
||||
@ -62,7 +62,7 @@ function onclickJoin(type, keyword) {
|
||||
}
|
||||
if (user_pw.value === user_pw_check.value) {
|
||||
if(confirm(JSON.stringify(data) + "\n해당 내용으로\n유저 등록 하실??")) {
|
||||
post("joinUser.ajax",type,JSON.stringify(data),keyword, function (resultData) {
|
||||
post("joinUser.bjx",type,JSON.stringify(data),keyword, function (resultData) {
|
||||
alert(resultData)
|
||||
})
|
||||
} else {
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
|
||||
layout:decorate="~{layout/default_layout}"
|
||||
>
|
||||
<th:block layout:fragment="head" id="head">
|
||||
@ -86,10 +88,10 @@
|
||||
</section>
|
||||
|
||||
<section class="wrapper style2">
|
||||
<th:block th:if="${PERMISSION != 'OK'}">
|
||||
<th:block sec:authorize="isAnonymous()">
|
||||
<h1>권한이 없는 뎁쇼?!</h1>
|
||||
</th:block>
|
||||
<th:block th:if="${PERMISSION == 'OK'}">
|
||||
<th:block sec:authorize="isAuthenticated()">
|
||||
<div id="editor" ></div>
|
||||
<div class="write_controllbox">
|
||||
<div class="write_option btn-example" to="#popLayer1" onclick="openPopup(this)" ></div>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
<th:block layout:fragment="head">
|
||||
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
|
||||
@ -33,10 +34,10 @@
|
||||
</th:block>
|
||||
<th:block layout:fragment="content" id="content">
|
||||
<div id="main_layer">
|
||||
<th:block th:if="${PERMISSION != 'OK'}">
|
||||
<th:block sec:authorize="isAnonymous()">
|
||||
<h1>권한이 없는 뎁쇼?!</h1>
|
||||
</th:block>
|
||||
<th:block th:if="${PERMISSION == 'OK'}">
|
||||
<th:block sec:authorize="isAuthenticated()">
|
||||
<div class="post_layer">
|
||||
<th:block class="posts_layer" id="posts" th:each="posts ,postsStat: ${chunkedPosts}">
|
||||
<th:block class="posts_layer" th:class="${#strings.append(rowKey,postsStat.index)}" th:each="post, postStast : ${posts}">
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}"
|
||||
>
|
||||
<th:block layout:fragment="head">
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}"
|
||||
>
|
||||
<th:block layout:fragment="head">
|
||||
@ -38,13 +39,13 @@
|
||||
<th:block layout:fragment="content" id="content">
|
||||
<section class="wrapper style2">
|
||||
|
||||
<div class="container" th:if="${PERMISSION == 'OK'}" onclick="loadEditor()">
|
||||
<div class="container" sec:authorize="isAuthenticated()" onclick="loadEditor()">
|
||||
<header class="major">
|
||||
<h2 id="title_layer" th:text="${srcPost.title}">A gigantic heading you can use for whatever</h2>
|
||||
<p th:text="${#temporals.format(T(java.time.Instant).ofEpochMilli(srcPost.writeTime).atZone(T(java.time.ZoneId).systemDefault()).toLocalDateTime(), 'yyyy-MM-dd HH:mm:ss')}"></p>
|
||||
</header>
|
||||
</div>
|
||||
<div class="container" th:if="${PERMISSION != 'OK'}" onclick="openLoginPopup('login')">
|
||||
<div class="container" sec:authorize="isAnonymous()" onclick="openLoginPopup('login')">
|
||||
<header class="major">
|
||||
<h2 id="title_layer" th:text="${srcPost.title}">A gigantic heading you can use for whatever</h2>
|
||||
<p th:text="${#temporals.format(T(java.time.Instant).ofEpochMilli(srcPost.writeTime).atZone(T(java.time.ZoneId).systemDefault()).toLocalDateTime(), 'yyyy-MM-dd HH:mm:ss')}"></p>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}"
|
||||
>
|
||||
<th:block layout:fragment="head" id="head">
|
||||
@ -100,10 +101,10 @@
|
||||
</th:block>
|
||||
<th:block layout:fragment="content" id="content">
|
||||
<div id="main_layer">
|
||||
<th:block th:if="${PERMISSION != 'OK'}">
|
||||
<th:block sec:authorize="isAnonymous()">
|
||||
<h1>권한이 없는 뎁쇼?!</h1>
|
||||
</th:block>
|
||||
<th:block th:if="${PERMISSION == 'OK'}">
|
||||
<th:block sec:authorize="isAuthenticated()">
|
||||
<div class="layer">
|
||||
<input id="title_field" class="write_option" />
|
||||
</div>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
<th:block layout:fragment="head">
|
||||
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
|
||||
@ -10,7 +11,7 @@
|
||||
<script type="text/javascript" th:src="@{/js/test.js}"></script>
|
||||
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener("DOMContentLoaded", onLoaded);
|
||||
// document.addEventListener("DOMContentLoaded", onLoaded);
|
||||
function goToViewer(item) {
|
||||
let uploadUrl = getMainPath() + "/blog/viewer/"+item.attributes['data'].value;
|
||||
location.href = uploadUrl
|
||||
@ -73,12 +74,12 @@
|
||||
</div>
|
||||
</section>
|
||||
<section class="col-4 col-12-narrower">
|
||||
<div class="box highlight" th:if="${PERMISSION == 'OK'}" onclick=gotoWrite()>
|
||||
<div class="box highlight" sec:authorize="isAuthenticated()" onclick=gotoWrite()>
|
||||
<i class="icon solid major fa-pencil-alt"></i>
|
||||
<h3>글쓰기[Writing]</h3>
|
||||
<p>오직 주인장 만의 권한 임요. 그냥 내가 쓰기 편하게 여기 놔둔 메뉴임. 님들은 못씀요.<br>[Only the owner has the authority. This is just a menu that I put here for my convenience. You can't use it.]</p>
|
||||
</div>
|
||||
<div class="box highlight" th:if="${PERMISSION != 'OK'}" onclick="openLoginPopup('login')">
|
||||
<div class="box highlight" sec:authorize="isAnonymous()" onclick="openLoginPopup('login')">
|
||||
<i class="icon solid major fa-pencil-alt"></i>
|
||||
<h3>글쓰기[Writing]</h3>
|
||||
<p>오직 주인장 만의 권한 임요. 그냥 내가 쓰기 편하게 여기 놔둔 메뉴임. 님들은 못씀요.<br>[Only the owner has the authority. This is just a menu that I put here for my convenience. You can't use it.]</p>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
<th:block layout:fragment="head">
|
||||
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
|
||||
layout:decorate="~{layout/default_layout}"
|
||||
>
|
||||
<th:block layout:fragment="head">
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
<th:block layout:fragment="head">
|
||||
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
<th:block layout:fragment="head">
|
||||
<link th:href="@{/css/private.css}" rel="stylesheet" />
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
<th:block layout:fragment="head">
|
||||
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
<th:block layout:fragment="head">
|
||||
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}"
|
||||
>
|
||||
<th:block layout:fragment="head" id="head">
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
layout:decorate="~{layout/default_layout}">
|
||||
|
||||
<head>
|
||||
|
||||
@ -1,39 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<th:block th:fragment="header">
|
||||
<div id="header">
|
||||
|
||||
<!-- Logo -->
|
||||
<h1><a th:href="@{/}" id="logo">BUM ' <em>sPace</em></a></h1>
|
||||
|
||||
<th:block sec:authorize="isAuthenticated()">
|
||||
<span style="margin-left:20px;">환영합니다, <b sec:authentication="name"></b>님!</span>
|
||||
</th:block>
|
||||
<!-- Nav -->
|
||||
<nav id="nav">
|
||||
<ul>
|
||||
<li id="menu_home" ><a th:href="@{/}">Home</a></li>
|
||||
<li id="menu_posts"><a href="blog/posts">Posts</a></li>
|
||||
|
||||
<li id="menu_sec"><a href="left-sidebar">Left Sidebar</a></li>
|
||||
<li id="menu_thr"><a href="right-sidebar">Right Sidebar</a></li>
|
||||
<li id="menu_four"><a href="two-sidebar">Two Sidebar</a></li>
|
||||
<!-- <li id="menu_sec"><a href="left-sidebar">Left Sidebar</a></li>-->
|
||||
<!-- <li id="menu_thr"><a href="right-sidebar">Right Sidebar</a></li>-->
|
||||
<!-- <li id="menu_four"><a href="two-sidebar">Two Sidebar</a></li>-->
|
||||
<li id="menu_drop">
|
||||
<a href="#">About</a>
|
||||
<ul>
|
||||
<li><a href="#">Lorem dolor</a></li>
|
||||
<li><a href="javascript:gotoWhere()">bums's where</a></li>
|
||||
<li><a href="#">Magna phasellus</a></li>
|
||||
<li><a href="#">Etiam sed tempus</a></li>
|
||||
<li>
|
||||
<a href="#">Submenu</a>
|
||||
<ul>
|
||||
<li><a href="#">Lorem dolor</a></li>
|
||||
<th:block sec:authorize="isAuthenticated()">
|
||||
<li><a href="javascript:gotoWrite()">글쓰기</a></li>
|
||||
<li><a href="javascript:gotoModify()">수정하기</a></li>
|
||||
</th:block>
|
||||
<li><a href="#">Phasellus magna</a></li>
|
||||
<li><a href="#">Magna phasellus</a></li>
|
||||
<li><a href="#">Etiam nisl</a></li>
|
||||
<li><a href="#">Veroeros feugiat</a></li>
|
||||
<!-- <li><a href="#">Magna phasellus</a></li>-->
|
||||
<!-- <li><a href="#">Etiam nisl</a></li>-->
|
||||
<!-- <li><a href="#">Veroeros feugiat</a></li>-->
|
||||
</ul>
|
||||
</li>
|
||||
<li><a th:href="@{/licenses}">Licenses</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<th:block sec:authorize="!isAuthenticated()">
|
||||
<li id="menu_login" ><a href="javascript:openLoginPopup('login')">LOGIN</a></li>
|
||||
</th:block>
|
||||
<th:block sec:authorize="isAuthenticated()">
|
||||
<li>
|
||||
<a href="javascript:logout()" style="margin-left:10px;">로그아웃</a>
|
||||
<li>
|
||||
</th:block>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
||||
@ -13,5 +13,7 @@
|
||||
<link rel="stylesheet" href="assets/css/main.css" />
|
||||
<script async th:src="@{https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9504446465764716}" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" th:src="@{/js/common.js}"></script>
|
||||
<meta name="_csrf" th:content="${_csrf.token}"/>
|
||||
<meta name="_csrf_parameter" th:content="${_csrf.parameterName}"/>
|
||||
</th:block>
|
||||
</html>
|
||||
@ -2,6 +2,7 @@
|
||||
<html lagn="ko"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
xmlns="http://www.w3.org/1999/html">
|
||||
<head>
|
||||
<base th:href="@{/}" />
|
||||
@ -20,12 +21,47 @@
|
||||
<th:block th:replace="~{fragments/footer :: footer}"></th:block>
|
||||
</div>
|
||||
<div id="overlay" class="login_overlay">
|
||||
<style>
|
||||
.custom-checkbox {
|
||||
display: none; /* 실제 체크박스 숨김 */
|
||||
}
|
||||
|
||||
.custom-label {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #555;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.custom-checkbox:checked + .custom-label {
|
||||
background-color: #007bff;
|
||||
border-color: #007bff;
|
||||
}
|
||||
|
||||
.custom-checkbox:checked + .custom-label::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 7px;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
||||
<div id="popup" class="login_popup">
|
||||
<div id="loginForm" class="login_form">
|
||||
<h2>로그인</h2>
|
||||
<form id="loginFormElement" onsubmit="return false;">
|
||||
<input type="text" th:data="${enc}" id="loginId" placeholder="아이디" required>
|
||||
<input type="password" th:data="${type}" id="loginPassword" placeholder="비밀번호" required>
|
||||
<input type="text" th:data="${enc}" id="loginId" placeholder="아이디" required/>
|
||||
<input type="password" th:data="${type}" id="loginPassword" placeholder="비밀번호" required/>
|
||||
<input type="checkbox" id="rememberMe" class="custom-checkbox"/>
|
||||
<label for="rememberMe" class="custom-label"></label>
|
||||
<span>자동로그인</span>
|
||||
<button type="submit" class="button">로그인</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user