Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
38a47db
feat: ã로그인 html 프로토타입 1.0
PDJ-N Jun 29, 2025
c7a1b89
bug: student static bug
SONGYOOCHAN Jul 5, 2025
32d0a5e
update: 프로젝트 버전을 자바 17로 변경
Duskafka Jul 5, 2025
0b9372d
feat: 메인화면 1.0 추가
PDJ-N Jul 12, 2025
22ec0ae
feat: 메인페이지 CSS 레이아웃 및 반응형 스타일 추가
PDJ-N Jul 12, 2025
bad5150
feat: 메인페이지 로고 SVG 이미지 리소스 추가
PDJ-N Jul 12, 2025
b44ef21
feat: 모바일 햄버거 메뉴 동작 및 오버레이 처리 기능 구현
PDJ-N Jul 12, 2025
6d46250
feat: 메인화면 1.0 추가
PDJ-N Jul 12, 2025
e0ea5bb
chore: 파일명 kebab-case로 변경 및 html defer속성 반영
PDJ-N Jul 13, 2025
08a826a
feat: login페이지 UI 최소구현 및 기본 기능 연결
PDJ-N Jul 14, 2025
40bf839
style: 로그인 화면 CSS 스타일 추가(보라)
PDJ-N Jul 15, 2025
035651d
chore: 로그인 js파일 내 주석 문장 정리
PDJ-N Jul 15, 2025
266c23d
feat: 회원가입 페이지 마크업 및 기본 폼 구현
PDJ-N Jul 16, 2025
00ea998
refactor(css): 공통 스타일 common.css로 분리하고 css, html 코드 수정
PDJ-N Jul 16, 2025
1315829
Merge pull request #2 from selab-hs/feature/mainpage-ui
PDJ-N Jul 16, 2025
a13c40e
refactor: 공통 스타일 common.css로 분리하고 수정
PDJ-N Jul 16, 2025
51665de
fix: 햄버거 버튼 표시 오류해결 및 색상 스타일 수정
PDJ-N Jul 16, 2025
bac5fd4
feat: 글쓰기 페이지 초기화면구성, 반응형 메뉴 추가
PDJ-N Jul 16, 2025
6423eaf
Merge pull request #5 from selab-hs/feature/mainpage-ui
PDJ-N Jul 19, 2025
ce4fde3
Merge pull request #3 from selab-hs/feature/login-page
PDJ-N Jul 19, 2025
664a2db
Merge pull request #4 from selab-hs/feature/signup-page
PDJ-N Jul 19, 2025
5b51fb3
Merge pull request #7 from selab-hs/feature/write-page
PDJ-N Jul 19, 2025
8543a29
feat(Auth): 회원가입 및 로그인 기능 구현
Duskafka Jul 22, 2025
756b571
fix : 이슈 #9 해결하였습니다
SONGYOOCHAN Jul 23, 2025
39790aa
fix : 이슈 #9 해결하였습니다
SONGYOOCHAN Jul 23, 2025
7f616d8
Merge remote-tracking branch 'origin/fix/9' into fix/9
SONGYOOCHAN Jul 23, 2025
c63867a
fix : 이슈 #9 해결하였습니다
SONGYOOCHAN Jul 23, 2025
10a99b2
Merge remote-tracking branch 'origin/fix/9' into fix/9
SONGYOOCHAN Jul 23, 2025
2085289
feat: 회원가입 JS 수정 - 백엔드 DTO 필드명에 맞게 JSON 구조 변경
PDJ-N Jul 24, 2025
9255dd6
feat: 회원가입 JS 수정 - 백엔드 DTO 필드명에 맞게 JSON 구조 변경
PDJ-N Jul 24, 2025
fb6316b
chore: 로그인 관련 코드 수정 보류 중 - bug report 참고
PDJ-N Jul 24, 2025
fe5b53e
feat: 회원가입 JS 수정 - 백엔드 DTO 필드명에 맞게 JSON 구조 변경
PDJ-N Jul 24, 2025
158f9cc
feat: 회원가입 JS 수정 - 백엔드 DTO 필드명에 맞게 JSON 구조 변경
PDJ-N Jul 24, 2025
8a8cb1d
chore: 로그인 관련 코드 수정 보류 중 - bug report 참고
PDJ-N Jul 24, 2025
1d0fcaf
fix: 접근 가능한 경로 수정
Duskafka Jul 25, 2025
d4a2c48
feat(View): 로그인 뷰 컨트롤러
Duskafka Jul 25, 2025
c9c357d
fix: 서버에 올바른 경로로 접근하여 CSS와 JS를 가져올 수 있도록 변경
Duskafka Jul 25, 2025
906eada
Merge remote-tracking branch 'origin/feature/14' into feature/14
Duskafka Jul 25, 2025
b677068
Merge pull request #17 from selab-hs/fix/9
SONGYOOCHAN Jul 25, 2025
98f7d9e
feat(auth-api): 아이디 중복 확인 API 초안 주석처리 상태로 추가
PDJ-N Jul 27, 2025
479c3e7
feat(ui-controller): 회원가입(sign-up) 페이지 라우팅 추가
PDJ-N Jul 27, 2025
ab0a7d6
chore(security): 아이디 중복 확인 API 허용 예정 주석 추가
PDJ-N Jul 27, 2025
8b3ef88
feat(login): 로그인 폼 처리 및 JWT 토큰 저장 기능 구현
PDJ-N Jul 27, 2025
07563e5
feat: 회원가입 페이지에 아이디 중복 확인 기능 UI 추가
PDJ-N Jul 27, 2025
d604d68
feat: 회원가입 스크립트에 아이디 중복 확인 및 유효성 검증 기능 추가
PDJ-N Jul 27, 2025
67a1073
Merge pull request #20 from selab-hs/feature/14
PDJ-N Jul 28, 2025
206aaca
feat: 이슈 #10에 관한 게시판 기능 구현하였습니다
SONGYOOCHAN Aug 1, 2025
66bf403
refactor: 게시판 기능에대한 PR사항 수정하였습니다
SONGYOOCHAN Aug 5, 2025
0a6fec9
refactor: 게시판 기능에대한 모든 PR사항 수정하였습니다
SONGYOOCHAN Aug 6, 2025
3d5212a
refactor: 게시판 기능에대한 모든 PR사항 수정하였습니다
SONGYOOCHAN Aug 6, 2025
1a294cd
Merge remote-tracking branch 'origin/feature/10' into feature/10
SONGYOOCHAN Aug 6, 2025
7abae92
refactor: 게시판 기능에대한 2차 PR사항 수정하였습니다
SONGYOOCHAN Aug 7, 2025
557eb9c
bug: Post기능 테스트시 401에러 발생
SONGYOOCHAN Aug 10, 2025
168f8dc
refactor: 인증 문제 관련 코드 수정완료
SONGYOOCHAN Aug 12, 2025
f305b01
refactor: 인증 문제 관련 코드 수정완료
SONGYOOCHAN Aug 12, 2025
46790f4
refactor: 인증 문제 관련 코드 수정완료
SONGYOOCHAN Aug 12, 2025
fdfe7f1
Merge branch 'dev' into feature/10
SONGYOOCHAN Aug 12, 2025
0b7b602
Merge pull request #22 from selab-hs/feature/10
SONGYOOCHAN Aug 12, 2025
7e1ca83
chore: 주석수정
PDJ-N Aug 12, 2025
66077a3
fix: 서버에 올바른 경로로 접근하여 CSS와 JS를 가져올 수 있도록 변경
PDJ-N Aug 12, 2025
6d0b4bf
feat: 로그인 아이디 중복 체크
Duskafka Aug 14, 2025
fcc01b0
feat: 로그인 아이디 중복 체크
Duskafka Aug 14, 2025
5b3f6ac
fix: 사용 가능한 아이디일 때 OK를 보내도록 수정
Duskafka Aug 14, 2025
5d68d9e
feat: Post를 가져올 때 사용자의 이름도 가져오도록 함
Duskafka Aug 14, 2025
7f949a0
update: 아이디 체크 및 게시글 조회 API 권한 수정
Duskafka Aug 14, 2025
791c1e6
delete: 불필요한 클래스 삭제
Duskafka Aug 14, 2025
143cb37
작업 내용 커밋
PDJ-N Aug 14, 2025
8b3e090
Merge dev into feature/13
PDJ-N Aug 14, 2025
d2cbe47
docs: SecurityConfig에 접근 정책과 필터 체인 동작 주석 보강
PDJ-N Aug 15, 2025
3b3f53d
fix: Student.hasRole 역동작 수정(noneMatch→anyMatch)으로 권한 판별정상화
PDJ-N Aug 15, 2025
a860123
feat: 회원가입 UX 개선 — 아이디 중복확인 레이스 가드·입력 검증·상태코드 처리 추가
PDJ-N Aug 15, 2025
8dc941a
feat: 상세/목록/검색 응답에 작성자 이름 포함 및 권한 검증 정비
PDJ-N Aug 15, 2025
328369e
feat: 상세/목록 응답에 작성자 이름 포함 및 쓰기 액션 권한 보강
PDJ-N Aug 15, 2025
e3a8ba2
feat(auth,posts,ui): 회원가입/로그인 폼 도입 및 JWT 연동 + 게시글 가드/UX 개선
PDJ-N Aug 15, 2025
7ec28ff
update: 수정 페이지 라우트 패턴 관련 코드 정리
PDJ-N Aug 15, 2025
3aa8684
chore: 불필요한 CORS 설정 코드 삭제
PDJ-N Aug 15, 2025
9529032
fix: localStorage 토큰 키값 및 사용 방식 수정
PDJ-N Aug 16, 2025
6311728
Merge pull request #30 from selab-hs/feature/13
PDJ-N Aug 16, 2025
ae7a1d2
fix: 아이디/중복확인 일직선 정렬 및 비밀번호 보기 아이콘 적용
PDJ-N Aug 16, 2025
81620e7
fix: 아이디/중복확인 일직선 정렬 및 비밀번호 보기 아이콘 적용
PDJ-N Aug 16, 2025
cd510cf
Merge pull request #32 from selab-hs/feature/31
PDJ-N Aug 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,51 @@ repositories {
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter'

// JPA
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'

// Thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'

// JWT
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'

// Spring Web
implementation 'org.springframework.boot:spring-boot-starter-web'

// Lombok
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'

// Database
implementation 'com.mysql:mysql-connector-j:8.2.0' // 보안 취약점 패치(>=8.2.0) 적용
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'

// Test tool
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'

// Querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"

// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
}

tasks.named('test') {
useJUnitPlatform()
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/demo/DemoApplication.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.demo;

import com.demo.config.properties.JWTProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(
JWTProperties.class
)
public class DemoApplication {

public static void main(String[] args) {
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/demo/config/CorsConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
* 애플리케이션에서 CORS 설정을 하기 위한 Configuration
*
* @author duskafka
* */
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/api/v1/**", config);
return new CorsFilter(source);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/demo/config/JpaConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

/**
* JPA 설정을 설정하기 위한 Configuration
*
* <li>JPAQueryFactory: Querydsl을 사용하기 위해 JPAQueryFactory를 빈으로 등록</li>
*
* @author duskafka
* */
@Slf4j
@EnableJpaAuditing
@Configuration
public class JpaConfig {

}
28 changes: 28 additions & 0 deletions src/main/java/com/demo/config/JwtSecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.demo.config;

import com.demo.config.properties.JWTProperties;
import com.demo.jwt.JwtFilter;
import com.demo.jwt.TokenProvider;
import com.demo.jwt.TokenValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@RequiredArgsConstructor
public class JwtSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final TokenProvider tokenProvider;
private final TokenValidator tokenValidator;
private final JWTProperties jwtProperties;

@Override
public void configure(HttpSecurity http) {
http.addFilterBefore(
new JwtFilter(tokenProvider, tokenValidator, jwtProperties),
UsernamePasswordAuthenticationFilter.class
);
}
}
104 changes: 104 additions & 0 deletions src/main/java/com/demo/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.demo.config;

import com.demo.config.properties.JWTProperties;
import com.demo.jwt.JwtAccessDeniedHandler;
import com.demo.jwt.JwtAuthenticationEntryPoint;
import com.demo.jwt.TokenProvider;
import com.demo.jwt.TokenValidator;
import com.demo.repository.StudentRepository;
import com.demo.service.CustomLoginService;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.cors.CorsUtils;

@Slf4j
@EnableWebSecurity
@EnableMethodSecurity
@Configuration
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class SecurityConfig {
private final CorsFilter corsFilter;
private final TokenProvider tokenProvider;
private final TokenValidator tokenValidator;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final JWTProperties jwtProperties;

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public CustomLoginService customLoginService(StudentRepository studentRepository) {
return new CustomLoginService(studentRepository);
}

@Bean
public AuthenticationManager authenticationManager(HttpSecurity http, PasswordEncoder passwordEncoder, CustomLoginService customLoginService) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(customLoginService)
.passwordEncoder(passwordEncoder)
.and()
.build();
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exception -> {
exception.accessDeniedHandler(jwtAccessDeniedHandler)
.authenticationEntryPoint(jwtAuthenticationEntryPoint);
})
.authorizeHttpRequests(request -> {
request
// UI 라우트: 비로그인 허용
.requestMatchers("/", "/sign-in", "/sign-up").permitAll()
.requestMatchers("/posts", "/posts/*", "/posts/edit/*").permitAll()
.requestMatchers("/js/**", "/css/**", "/images/**", "/favicon.ico", "/error").permitAll()

// API 조회는 비로그인 허용
.requestMatchers(HttpMethod.GET, "/api/v1/posts/**").permitAll()

// API 쓰기 작업은 인증 필요
.requestMatchers(HttpMethod.POST, "/api/v1/posts/**").authenticated()
.requestMatchers(HttpMethod.PUT, "/api/v1/posts/**").authenticated()
.requestMatchers(HttpMethod.DELETE, "/api/v1/posts/**").authenticated()

// 나머지 기존 정책
.requestMatchers("/api/v1/auth/login", "/api/v1/auth/register", "/api/v1/auth/check-id").permitAll()
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
.requestMatchers("/api/v1/students/**").hasAnyRole("ADMIN", "USER")
.requestMatchers(org.springframework.web.cors.CorsUtils::isPreFlightRequest).permitAll()
.anyRequest().authenticated();
})
.sessionManagement(session -> {
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
})
.headers(headers -> {
headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin);
})
.with(new JwtSecurityConfig(tokenProvider, tokenValidator, jwtProperties), customizer -> {
});
return http.build();
}
}
28 changes: 28 additions & 0 deletions src/main/java/com/demo/config/properties/JWTProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.demo.config.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* JWT 토큰 프로퍼티를 가지는 클래스
*
* @author duskafka
* */
@ConfigurationProperties(prefix = "jwt")
public record JWTProperties(
//JWT 토큰이 HTTP 헤더에 담길 때 사용될 헤더 이름 (예: Authorization)
String accessTokenHeader,

//JWT 서명 및 검증에 사용될 비밀 키 (Base64 인코딩된 문자열)
//HS512 알고리즘을 사용할 것이기 때문에 512bit, 즉 64byte 이상의 secret key를 사용해야 합니다.
String secret,

//Access Token의 만료 기간 (초 단위)
long accessTokenValidityInHour,

//인증용 키
String authorityKey,

//액세스 토큰 인증 헤더
String bearerHeader
) {
}
45 changes: 0 additions & 45 deletions src/main/java/com/demo/controller/ApiController.java

This file was deleted.

Loading