From 5aade9edf89f1463b5d0d5a34ab39825c8e07c40 Mon Sep 17 00:00:00 2001 From: aqrms Date: Tue, 21 Nov 2023 10:44:13 +0900 Subject: [PATCH 01/21] [feat] #118. Apply gitignore to logfiles --- backend/orury/.gitignore | 1 + .../main/java/com/kernel360/orury/config/SecurityConfig.java | 1 + .../kernel360/orury/domain/admin/service/AdminPostService.java | 2 -- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/orury/.gitignore b/backend/orury/.gitignore index d99209a..863e9a4 100644 --- a/backend/orury/.gitignore +++ b/backend/orury/.gitignore @@ -6,6 +6,7 @@ build/ !**/src/test/**/build/ LOCAL_LOG_URL_IS_UNDEFINED .DS_Store +AWS_LOG_URL_IS_UNDEFINED/ ### STS ### .apt_generated diff --git a/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java b/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java index 8960757..80a36ca 100644 --- a/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java +++ b/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; diff --git a/backend/orury/src/main/java/com/kernel360/orury/domain/admin/service/AdminPostService.java b/backend/orury/src/main/java/com/kernel360/orury/domain/admin/service/AdminPostService.java index 95bd13d..a8b4699 100644 --- a/backend/orury/src/main/java/com/kernel360/orury/domain/admin/service/AdminPostService.java +++ b/backend/orury/src/main/java/com/kernel360/orury/domain/admin/service/AdminPostService.java @@ -39,8 +39,6 @@ public PostDto createPost( .postContent(postRequest.getPostContent()) .userId(1L) .board(boardEntity) - // .thumbnailUrl(postRequest.getPostImageList().isEmpty() ? null : postRequest.getPostImageList().get(0)) - // .images(postRequest.getPostImageList().isEmpty() ? null : String.join(",", postRequest.getPostImageList())) .createdBy(Constant.ADMIN.getMessage()) .createdAt(LocalDateTime.now()) .updatedBy(Constant.ADMIN.getMessage()) From f47bf58762542b7db1cf6370e9b683a4c3d4ec05 Mon Sep 17 00:00:00 2001 From: aqrms Date: Tue, 21 Nov 2023 19:22:25 +0900 Subject: [PATCH 02/21] Add AdminAuthorizationFilter --- .../orury/config/SecurityConfig.java | 74 +++++++++- .../orury/config/jwt/TokenProvider.java | 92 +++++++------ .../jwt/admin/AdminAuthenticationFilter.java | 87 ++++++++++++ .../jwt/admin/AdminAuthorizationFilter.java | 130 ++++++++++++++++++ .../controller/AdminBoardController.java | 5 + .../orury/src/main/resources/application.yml | 21 +-- .../templates/layout/charts-apexcharts.html | 2 +- .../templates/layout/charts-chartjs.html | 2 +- .../templates/layout/charts-echarts.html | 2 +- .../layout/components-accordion.html | 2 +- .../templates/layout/components-alerts.html | 2 +- .../templates/layout/components-badges.html | 2 +- .../layout/components-breadcrumbs.html | 2 +- .../templates/layout/components-buttons.html | 2 +- .../templates/layout/components-cards.html | 2 +- .../templates/layout/components-carousel.html | 2 +- .../layout/components-list-group.html | 2 +- .../templates/layout/components-modal.html | 2 +- .../layout/components-pagination.html | 2 +- .../templates/layout/components-progress.html | 2 +- .../templates/layout/components-spinners.html | 2 +- .../templates/layout/components-tabs.html | 2 +- .../templates/layout/components-tooltips.html | 2 +- .../templates/layout/forms-editors.html | 2 +- .../templates/layout/forms-elements.html | 2 +- .../templates/layout/forms-layouts.html | 2 +- .../templates/layout/forms-validation.html | 2 +- .../templates/layout/icons-bootstrap.html | 2 +- .../templates/layout/icons-boxicons.html | 2 +- .../templates/layout/icons-remix.html | 2 +- .../templates/layout/pages-blank.html | 2 +- .../templates/layout/pages-contact.html | 2 +- .../resources/templates/layout/pages-faq.html | 2 +- .../templates/layout/pages-register.html | 2 +- .../templates/layout/tables-general.html | 2 +- .../templates/layout/users-profile.html | 2 +- .../templates/{layout => }/pages-login.html | 4 +- 37 files changed, 384 insertions(+), 89 deletions(-) create mode 100644 backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthenticationFilter.java create mode 100644 backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthorizationFilter.java rename backend/orury/src/main/resources/templates/{layout => }/pages-login.html (95%) diff --git a/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java b/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java index 80a36ca..5d6f748 100644 --- a/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java +++ b/backend/orury/src/main/java/com/kernel360/orury/config/SecurityConfig.java @@ -1,13 +1,18 @@ package com.kernel360.orury.config; import com.kernel360.orury.config.jwt.*; +import com.kernel360.orury.config.jwt.admin.AdminAuthenticationFilter; +import com.kernel360.orury.config.jwt.admin.AdminAuthorizationFilter; +import com.kernel360.orury.domain.user.db.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; @@ -15,9 +20,12 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.web.filter.CorsFilter; import java.util.List; +import java.util.Map; /** author : aqrms @@ -36,10 +44,18 @@ public class SecurityConfig { "/api/notify/**" // sse 테스트를 위해 임시로 ); private final TokenProvider tokenProvider; + private final UserRepository userRepository; private final CorsFilter corsFilter; private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; private final JwtAccessDeniedHandler jwtAccessDeniedHandler; - private CustomAuthenticationFailureHandler failureHandler; + @Value("${token.cookie.name}") + private String cookieName; + @Value("${token.cookie.refresh-name}") + private String cookieRefreshName; + @Value("${jwt.access-validity}") + private String accessCookieMaxAge; + @Value("${jwt.refresh-validity}") + private String refreshCookieMaxAge; @Bean public PasswordEncoder passwordEncoder() { @@ -47,9 +63,59 @@ public PasswordEncoder passwordEncoder() { } @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + @Order(1) + public SecurityFilterChain adminFilterChain(HttpSecurity http) throws Exception { + AuthenticationManager authenticationManager = (AuthenticationManager)http.getSharedObjects(); http - // token을 사용하는 방식이기 때문에 csrf를 disable합니다. + .requestMatchers(requestMatchers -> requestMatchers + .antMatchers("/admin/**") + ) + .csrf().disable() + .httpBasic().disable() + + .addFilterBefore(new AdminAuthenticationFilter( + authenticationManager, + tokenProvider, + cookieName, + cookieRefreshName, + accessCookieMaxAge, + refreshCookieMaxAge + ), + UsernamePasswordAuthenticationFilter.class) + .addFilterBefore( + new AdminAuthorizationFilter( + userRepository, + tokenProvider, + cookieName, + cookieRefreshName, + accessCookieMaxAge), + BasicAuthenticationFilter.class + ) + .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests + .antMatchers("/assets/**").permitAll() + .anyRequest().authenticated() + ) + .formLogin() + .loginPage("/admin/login") + .usernameParameter("emailAddr") + .passwordParameter("password") + .failureUrl("/admin/login") + .permitAll(); + http + .logout() + .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .logoutSuccessUrl("/admin") + .invalidateHttpSession(true); + return http.build(); + } + + @Bean + @Order(2) + public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception { + http + .requestMatchers(requestMatchers -> requestMatchers + .antMatchers("/api/**") + ) .csrf(csrf -> csrf.disable()) .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) @@ -60,8 +126,6 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests .mvcMatchers(SWAGGER.toArray(new String[0])).permitAll() - .antMatchers("/assets/**").permitAll() - .antMatchers("/admin/**").permitAll() .antMatchers("/api/hello", "/api/auth/login", "/api/user/signup").permitAll() .anyRequest().authenticated() ) diff --git a/backend/orury/src/main/java/com/kernel360/orury/config/jwt/TokenProvider.java b/backend/orury/src/main/java/com/kernel360/orury/config/jwt/TokenProvider.java index d89b847..174a832 100644 --- a/backend/orury/src/main/java/com/kernel360/orury/config/jwt/TokenProvider.java +++ b/backend/orury/src/main/java/com/kernel360/orury/config/jwt/TokenProvider.java @@ -11,6 +11,7 @@ import com.kernel360.orury.global.exception.TokenExpiredException; import com.kernel360.orury.global.exception.TokenNotFoundException; import com.kernel360.orury.global.message.errors.ErrorMessages; + import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; @@ -54,7 +55,7 @@ public TokenProvider( @Value("${jwt.secret}") String secret, UserRepository userRepository, RefreshTokenRepository tokenRepository - ) { + ) { this.refreshValidityMs = refershValiditySec * 1000L; this.accessValidityMs = accessValiditySec * 1000L; this.secret = secret; @@ -69,52 +70,51 @@ public void afterPropertiesSet() { this.key = Keys.hmacShaKeyFor(keyBytes); } - - - public String createAccessToken(Authentication authentication){ + public String createAccessToken(Authentication authentication) { String authorities = authentication.getAuthorities().stream() - .map(GrantedAuthority::getAuthority) - .collect(Collectors.joining(",")); + .map(GrantedAuthority::getAuthority) + .collect(Collectors.joining(",")); long now = (new Date()).getTime(); Date validity = new Date(now + accessValidityMs); UserEntity user = userRepository.findByEmailAddr(authentication.getName()).orElseThrow( - ()-> new RuntimeException(ErrorMessages.THERE_IS_NO_USER.getMessage()) + () -> new RuntimeException(ErrorMessages.THERE_IS_NO_USER.getMessage()) ); return Jwts.builder() - .claim(Constant.USERID.getMessage(), user.getId()) - .setSubject(authentication.getName()) - .claim(AUTHORITIES_KEY, authorities) - .signWith(key, SignatureAlgorithm.HS512) - .setExpiration(validity) - .compact(); + .claim(Constant.USERID.getMessage(), user.getId()) + .setSubject(authentication.getName()) + .claim(AUTHORITIES_KEY, authorities) + .signWith(key, SignatureAlgorithm.HS512) + .setExpiration(validity) + .compact(); } - public String createRefreshToken(Authentication authentication){ + + public String createRefreshToken(Authentication authentication) { long now = (new Date()).getTime(); Date validity = new Date(now + this.refreshValidityMs); // var userId = userRepository.findByEmailAddr(authentication.getName()).orElseThrow( - ()-> new RuntimeException(ErrorMessages.THERE_IS_NO_USER.getMessage()) + () -> new RuntimeException(ErrorMessages.THERE_IS_NO_USER.getMessage()) ).getId(); return Jwts.builder() - .claim( Constant.USERID.getMessage(), userId) - .signWith(key, SignatureAlgorithm.HS512) - .setExpiration(validity) - .compact(); + .claim(Constant.USERID.getMessage(), userId) + .signWith(key, SignatureAlgorithm.HS512) + .setExpiration(validity) + .compact(); } // 토큰을 파라미터로 받아서 클레임을 만들고 이를 이용해 유저 객체를 만들고 Authentication 객체 리턴 public Authentication getAuthentication(String token) throws JsonProcessingException { -// Claims claims = Jwts -// .parserBuilder() -// .setSigningKey(key) -// .build() -// .parseClaimsJws(token) -// .getBody(); - + // Claims claims = Jwts + // .parserBuilder() + // .setSigningKey(key) + // .build() + // .parseClaimsJws(token) + // .getBody(); + String[] chunks = token.split("\\."); String payload = new String(Base64.getUrlDecoder().decode(chunks[1])); @@ -123,7 +123,7 @@ public Authentication getAuthentication(String token) throws JsonProcessingExcep JsonNode jsonNode = objectMapper.readTree(payload); // 필요한 정보 추출 -// String userId = jsonNode.get("userId").asText(); + // String userId = jsonNode.get("userId").asText(); String sub = jsonNode.get("sub").asText(); String auth = jsonNode.get("auth").asText(); @@ -137,43 +137,42 @@ public Authentication getAuthentication(String token) throws JsonProcessingExcep return new UsernamePasswordAuthenticationToken(principal, token, authorities); } - - public boolean validateToken(String token ) throws ExpiredJwtException{ + public boolean validateToken(String token) throws ExpiredJwtException { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); return true; } - public void storeToken(String token){ + public void storeToken(String token) { Claims claims = Jwts - .parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token) - .getBody(); + .parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); var userId = Long.parseLong(claims.get("userId").toString()); var user = userRepository.findById(userId).orElseThrow( - () -> new RuntimeException(ErrorMessages.THERE_IS_NO_USER.getMessage()) + () -> new RuntimeException(ErrorMessages.THERE_IS_NO_USER.getMessage()) ); RefreshTokenEntity existingToken = refreshTokenRepository.findByUserId(userId).orElse(null); - if(existingToken != null){ + if (existingToken != null) { refreshTokenRepository.delete(existingToken); } var expiredDate = claims.getExpiration().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); var refreshTokenEntity = RefreshTokenEntity.builder() - .tokenValue(token) - .user(user) - .expirationDate(expiredDate) - .build(); + .tokenValue(token) + .user(user) + .expirationDate(expiredDate) + .build(); refreshTokenRepository.save(refreshTokenEntity); } public boolean validateRefreshToken(String refreshToken) { var refreshTokenEntity = refreshTokenRepository.findByTokenValue(refreshToken).orElseThrow( - () -> new TokenNotFoundException(ErrorMessages.ILLEGAL_REFRESH_JWT.getMessage()) + () -> new TokenNotFoundException(ErrorMessages.ILLEGAL_REFRESH_JWT.getMessage()) ); var expireDate = refreshTokenEntity.getExpirationDate(); @@ -184,5 +183,14 @@ public boolean validateRefreshToken(String refreshToken) { return validateToken(refreshToken); } + public boolean isTokenExpired(String token) { + Date expirationDate = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody() + .getExpiration(); + return expirationDate.before(new Date()); + } } \ No newline at end of file diff --git a/backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthenticationFilter.java b/backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthenticationFilter.java new file mode 100644 index 0000000..72a208c --- /dev/null +++ b/backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthenticationFilter.java @@ -0,0 +1,87 @@ +package com.kernel360.orury.config.jwt.admin; + +import java.io.IOException; +import java.util.ArrayList; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import com.kernel360.orury.config.jwt.TokenProvider; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class AdminAuthenticationFilter extends UsernamePasswordAuthenticationFilter { + + private final AuthenticationManager authenticationManager; + private final TokenProvider tokenProvider; + private final String cookieName; + private final String cookieRefreshName; + private final String accessCookieMaxAge; + private final String refreshCookieMaxAge; + + @Override + public Authentication attemptAuthentication( + HttpServletRequest request, + HttpServletResponse response + ) throws AuthenticationException { + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( + request.getParameter("userEmail"), + request.getParameter("password"), + new ArrayList<>() + ); + return authenticationManager.authenticate(authenticationToken); + } + + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, + Authentication authResult) throws IOException, ServletException { + String accessToken = tokenProvider.createAccessToken(authResult); + String refreshToken = tokenProvider.createRefreshToken(authResult); + tokenProvider.storeToken(refreshToken); + + addAuthenticationCookie(request, response, accessToken, true); + addAuthenticationCookie(request, response, refreshToken, false); + + String preLoginUrl = request.getParameter("preLoginUrl"); + if (preLoginUrl != null && !preLoginUrl.isBlank()) { + response.sendRedirect(preLoginUrl); + } else { + response.sendRedirect("/admin"); + } + } + + private void addAuthenticationCookie(HttpServletRequest request, HttpServletResponse response, String token, + boolean isAccessToken) { + Cookie authCookie; + int maxAge; + + if (isAccessToken) { + authCookie = new Cookie(cookieName, token); + maxAge = Integer.parseInt(accessCookieMaxAge) * 1000; + } else { + authCookie = new Cookie(cookieRefreshName, token); + maxAge = Integer.parseInt(refreshCookieMaxAge) * 1000; + } + authCookie.setMaxAge(maxAge); + authCookie.setPath("/"); + authCookie.setHttpOnly(true); + authCookie.setSecure(request.isSecure()); + response.addCookie(authCookie); + } + + @Override + protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, + AuthenticationException failed) throws IOException, ServletException { + response.sendRedirect("/admin/login"); + } +} diff --git a/backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthorizationFilter.java b/backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthorizationFilter.java new file mode 100644 index 0000000..04ec002 --- /dev/null +++ b/backend/orury/src/main/java/com/kernel360/orury/config/jwt/admin/AdminAuthorizationFilter.java @@ -0,0 +1,130 @@ +package com.kernel360.orury.config.jwt.admin; + +import java.io.IOException; +import java.util.Collections; +import java.util.Optional; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import com.kernel360.orury.config.jwt.TokenProvider; +import com.kernel360.orury.domain.user.db.UserRepository; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class AdminAuthorizationFilter extends OncePerRequestFilter { + + private final UserRepository userRepository; + private final TokenProvider tokenProvider; + private final String cookieName; + private final String cookieRefreshName; + private final String accessCookieMaxAge; + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain chain + ) throws IOException, ServletException { + + Optional accessToken = extractTokenFromCookie(request, cookieName); + Optional refreshToken = extractTokenFromCookie(request, cookieRefreshName); + + if (accessToken.isPresent()) { + processAccessToken(accessToken.get(), response); + } else { + refreshToken.ifPresentOrElse( + presentRefreshToken -> processRefreshToken(presentRefreshToken, response), + () -> clearAuthenticationAndCookie(response) + ); + } + + chain.doFilter(request, response); + } + + private void processAccessToken(String accessToken, HttpServletResponse response) { + if (tokenProvider.isTokenExpired(accessToken)) { + clearAuthenticationAndCookie(response); + } else { + validateAndAuthenticateToken(response, accessToken); + } + } + + private void processRefreshToken(String refreshToken, HttpServletResponse response) { + if (!tokenProvider.isTokenExpired(refreshToken)) { + try { + String newAccessToken = tokenProvider.createAccessTokenByRefreshToken(refreshToken); + addAuthenticationCookie(response, newAccessToken); + validateAndAuthenticateToken(response, newAccessToken); + } catch (Exception e) { + clearAuthenticationAndCookie(response); + } + } else { + clearAuthenticationAndCookie(response); + } + } + + private Optional extractTokenFromCookie(HttpServletRequest request, String cookieName) { + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookieName.equals(cookie.getName())) { + return Optional.of(cookie.getValue()); + } + } + } + return Optional.empty(); + } + + private void addAuthenticationCookie(HttpServletResponse response, String token) { + Cookie accessTokenCookie = new Cookie(cookieName, token); + accessTokenCookie.setHttpOnly(true); + accessTokenCookie.setPath("/"); + accessTokenCookie.setMaxAge(Integer.parseInt(accessCookieMaxAge) * 1000); + response.addCookie(accessTokenCookie); + } + + private void validateAndAuthenticateToken(HttpServletResponse response, String token) { + try { + if (tokenProvider.validateToken(token)) { + Authentication authentication = tokenProvider.getAuthentication(token); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + // String userEmail = tokenProvider.getUserEmail(token); + // userRepository.findActiveUserByUserEmail(userEmail).ifPresent(user -> { + // Authentication auth = getAuthentication(user); + // SecurityContextHolder.getContext().setAuthentication(auth); + // }); + } catch (Exception e) { + clearAuthenticationAndCookie(response); + } + } + + // private Authentication getAuthentication(User user) { + // return new UsernamePasswordAuthenticationToken( + // user.getUserName(), + // null, + // Collections.singletonList( + // new SimpleGrantedAuthority("ROLE_" + user.getUserPermissionType().getValue().toUpperCase())) + // ); + // } + + private void clearAuthenticationAndCookie(HttpServletResponse response) { + SecurityContextHolder.clearContext(); + Cookie cookie = new Cookie(cookieName, null); + cookie.setPath("/"); + cookie.setHttpOnly(true); + cookie.setMaxAge(0); + response.addCookie(cookie); + } +} diff --git a/backend/orury/src/main/java/com/kernel360/orury/domain/admin/controller/AdminBoardController.java b/backend/orury/src/main/java/com/kernel360/orury/domain/admin/controller/AdminBoardController.java index c7070a7..1560518 100644 --- a/backend/orury/src/main/java/com/kernel360/orury/domain/admin/controller/AdminBoardController.java +++ b/backend/orury/src/main/java/com/kernel360/orury/domain/admin/controller/AdminBoardController.java @@ -25,6 +25,11 @@ public class AdminBoardController { private final BoardService boardService; + @GetMapping("/login") + public String login() { + return "pages-login"; + } + @GetMapping public String index() { return "index"; diff --git a/backend/orury/src/main/resources/application.yml b/backend/orury/src/main/resources/application.yml index e4ba82f..f38f31a 100644 --- a/backend/orury/src/main/resources/application.yml +++ b/backend/orury/src/main/resources/application.yml @@ -19,18 +19,19 @@ spring: show_sql: true datasource: driver-class-name: com.mysql.cj.jdbc.Driver -# url: ${LOCAL_DB_URL} # configuration에서 설정 필요 - url: ENC(4t9k8jNC5SIDd1hpsqRJiw5NgwtRAZ9l2cY42PcN3v6GNDC61KXk4X3nYwwUdW4+aC6g41zh14HyfWg+2fPmfuTXHg7aw+vTvL9Oomq1wEKM2r2ZHJbhmakdpmbeMVjVALC/MSk28Tp4a5sBhUFRWdpaFO2qQcpdUHUd9KsuJh0=) -# username: ${LOCAL_DB_USERNAME} - username: ENC(2STroDy2TfWobkrTroFwbRcxLke05156ZFMrqwKmVssNcN4foSX4I6ax8YAgdW3R) -# password: ${LOCAL_DB_USER_PASSWORD} - password: ENC(a8l7l/AYNz2x1HPYyu+urOBwVcBhQkeWgTi6Fvt+lQFq1QyHsL8yyi5+wr7lh26P) + url: ${LOCAL_DB_URL} # configuration에서 설정 필요 + # url: ENC(4t9k8jNC5SIDd1hpsqRJiw5NgwtRAZ9l2cY42PcN3v6GNDC61KXk4X3nYwwUdW4+aC6g41zh14HyfWg+2fPmfuTXHg7aw+vTvL9Oomq1wEKM2r2ZHJbhmakdpmbeMVjVALC/MSk28Tp4a5sBhUFRWdpaFO2qQcpdUHUd9KsuJh0=) + username: ${LOCAL_DB_USERNAME} + # username: ENC(2STroDy2TfWobkrTroFwbRcxLke05156ZFMrqwKmVssNcN4foSX4I6ax8YAgdW3R) + password: ${LOCAL_DB_USER_PASSWORD} +# password: ENC(a8l7l/AYNz2x1HPYyu+urOBwVcBhQkeWgTi6Fvt+lQFq1QyHsL8yyi5+wr7lh26P) jwt: header: Authorization #HS512 알고리즘을 사용할 것이기 때문에 512bit, 즉 64byte 이상의 secret key를 사용해야 한다. #echo 'silvernine-tech-spring-boot-jwt-tutorial-secret-silvernine-tech-spring-boot-jwt-tutorial-secret'|base64 -# secret: ${LOCAL_JWT_SECRET_KEY} - secret: ENC(XNkGVBeK1sJZhLhri+zz7pJOhHCvfif265mvT8OUIbOGeQcOCtHNnG2s3qjsKNe2u+dLoNVQBzbF1bKUfDxi8Po5tL7jQbZMPA33Dg1QMQFQWV46IyrYnLykYXQQvpin/SNPXW04ECDoRLF3TNwcS22D8uWEwe8L2wtcauyHeO1z+J6lUQArPHy76O2pzC7FHlBjOTw3STd23e3dd1WBQtHAYVmOIvNuPreulzSaHXc=) - access-validity: 36000 - refresh-validity: 7200 + secret: ${LOCAL_JWT_SECRET_KEY} + # secret: ENC(XNkGVBeK1sJZhLhri+zz7pJOhHCvfif265mvT8OUIbOGeQcOCtHNnG2s3qjsKNe2u+dLoNVQBzbF1bKUfDxi8Po5tL7jQbZMPA33Dg1QMQFQWV46IyrYnLykYXQQvpin/SNPXW04ECDoRLF3TNwcS22D8uWEwe8L2wtcauyHeO1z+J6lUQArPHy76O2pzC7FHlBjOTw3STd23e3dd1WBQtHAYVmOIvNuPreulzSaHXc=) + access-validity: 20 + refresh-validity: 604800 + diff --git a/backend/orury/src/main/resources/templates/layout/charts-apexcharts.html b/backend/orury/src/main/resources/templates/layout/charts-apexcharts.html index 243ab4c..2614ff7 100644 --- a/backend/orury/src/main/resources/templates/layout/charts-apexcharts.html +++ b/backend/orury/src/main/resources/templates/layout/charts-apexcharts.html @@ -484,7 +484,7 @@
Kevin Anderson