nitial commit

This commit is contained in:
2026-05-15 10:36:20 +09:00
commit 2b16d1a3e1
18 changed files with 705 additions and 0 deletions
@@ -0,0 +1,13 @@
package company.specialsource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpecialsourceHomepageApplication {
public static void main(String[] args) {
SpringApplication.run(SpecialsourceHomepageApplication.class, args);
}
}
@@ -0,0 +1,32 @@
package company.specialsource.config;
import company.specialsource.entity.User;
import company.specialsource.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; // 로그를 위해 추가
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
@Slf4j // 로그 라이브러리
public class DataInitializer implements CommandLineRunner {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Override
public void run(String... args) {
if (userRepository.findByUsername("admin").isEmpty()) {
userRepository.save(User.builder()
.username("admin")
.password(passwordEncoder.encode("1234"))
.role("ROLE_USER")
.build());
log.info("초기 관리자 계정(admin)이 생성되었습니다.");
} else {
log.info("이미 관리자 계정이 존재합니다.");
}
}
}
@@ -0,0 +1,33 @@
package company.specialsource.config;
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableEncryptableProperties
public class JasyptConfig {
@Value("${jasypt.encryptor.password}")
private String password;
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(password); // 암호화 키 (절대 외부에 유출 금지!)
config.setAlgorithm("PBEWithMD5AndDES");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
@@ -0,0 +1,31 @@
package company.specialsource.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // REST API 통신을 위해 CSRF 비활성화
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/login").permitAll() // 로그인 API는 누구나 접근 가능
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // BCrypt 암호화 알고리즘 사용
}
}
@@ -0,0 +1,26 @@
package company.specialsource.controller;
import company.specialsource.dto.LoginRequest;
import company.specialsource.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class AuthController {
private final UserService userService;
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody LoginRequest loginRequest) {
boolean isSuccess = userService.login(loginRequest.getUsername(), loginRequest.getPassword());
if (isSuccess) {
return ResponseEntity.ok("로그인 성공!");
} else {
return ResponseEntity.status(401).body("아이디 또는 비밀번호가 틀렸습니다.");
}
}
}
@@ -0,0 +1,10 @@
package company.specialsource.dto;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class LoginRequest {
private String username;
private String password;
}
@@ -0,0 +1,25 @@
package company.specialsource.entity;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Table(name = "users") // PostgreSQL에서 'user'는 예약어이므로 'users' 테이블 명칭 권장
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password;
private String role; // 예: ROLE_USER, ROLE_ADMIN
}
@@ -0,0 +1,10 @@
package company.specialsource.repository;
import company.specialsource.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
// 사용자 아이디로 정보를 찾아오는 메서드
Optional<User> findByUsername(String username);
}
@@ -0,0 +1,28 @@
package company.specialsource.service;
import company.specialsource.entity.User;
import company.specialsource.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public boolean login(String username, String password) {
Optional<User> userOptional = userRepository.findByUsername(username);
if (userOptional.isPresent()) {
User user = userOptional.get();
// DB의 암호화된 비번과 입력받은 평문 비번 비교
return passwordEncoder.matches(password, user.getPassword());
}
return false;
}
}
+18
View File
@@ -0,0 +1,18 @@
spring:
datasource:
url: jdbc:postgresql://192.168.0.215:5435/mydb
username: headporter
password: ENC(Gg03NzjjcVOrFSXoBrPEusNgDNbYOPO4)
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update # 테이블 자동 생성
show-sql: true # SQL 로그 출력
properties:
hibernate:
format_sql: true
jasypt:
encryptor:
password: 81sungjin1015
@@ -0,0 +1,2 @@
$env:JASYPT_ENCRYPTOR_PASSWORD="81sungjin1015"
./gradlew bootRun