{"id":15068859,"url":"https://github.com/matrixpower1004/spring-security-bankapp","last_synced_at":"2026-01-03T06:11:10.970Z","repository":{"id":183031609,"uuid":"669495402","full_name":"matrixpower1004/Spring-Security-bankapp","owner":"matrixpower1004","description":"Bank App 을 개발하며 Spring Security의 설정과 Security 환경에서 Juni test 방법에 대해 학습한다.","archived":false,"fork":false,"pushed_at":"2023-08-08T15:50:06.000Z","size":235,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-01-22T21:32:35.529Z","etag":null,"topics":["gradle","java11","jpa-hibernate","lombok","secutiry","spring","springboot2","validation","web"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matrixpower1004.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-07-22T13:15:44.000Z","updated_at":"2023-07-29T13:14:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"d697b27d-d912-4d01-ab2c-262c55a9b140","html_url":"https://github.com/matrixpower1004/Spring-Security-bankapp","commit_stats":{"total_commits":30,"total_committers":2,"mean_commits":15.0,"dds":"0.30000000000000004","last_synced_commit":"82ad6e94381f3427690acff5defaaa83a23fcf52"},"previous_names":["matrixpower1004/spring-security","matrixpower1004/spring-security-bankapp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matrixpower1004%2FSpring-Security-bankapp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matrixpower1004%2FSpring-Security-bankapp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matrixpower1004%2FSpring-Security-bankapp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matrixpower1004%2FSpring-Security-bankapp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matrixpower1004","download_url":"https://codeload.github.com/matrixpower1004/Spring-Security-bankapp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243848978,"owners_count":20357684,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle","java11","jpa-hibernate","lombok","secutiry","spring","springboot2","validation","web"],"created_at":"2024-09-25T01:39:31.791Z","updated_at":"2026-01-03T06:11:10.918Z","avatar_url":"https://github.com/matrixpower1004.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Security with Junit Bank App\n\n### Jpa LocalDateTime 자동으로 생성하는 법\n- `@EnableJpaAuditing` (Main Application 에)\n- `@EntityListeners(AuditingEntityListener.class)` (Entity class 에)\n```java\n    @CreatedDate // insert 할 때 자동으로 날짜가 들어감\n    @Column(nullable = false)\n    private LocalDateTime createdAt;\n\n    @LastModifiedDate // insert, update 할 때 자동으로 날짜가 들어감\n    @Column(nullable = false)\n    private LocalDateTime updatedAt;\n```\n### Spring Security 설정 방법 변경(without WebSecurityConfigurerAdapter)\n스프링 부트 2.7(스프링 시큐리티 5.7) 부터 시큐리티 설정 방법이 변경되었다. WebSecurityConfigurerAdapter는 deprecated되었고, SecurityFilterChain을 사용해야 한다.\n- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes#migrating-from-websecurityconfigureradapter-to-securityfilterchain\n- https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter\n\n### 학습 노트\n- 스프링이 객체를 생성할 때 빈 생성자로 new 을 하기 때문에 parameter를 주입 받는 생성자를 수동으로 만들었다면 `@NoArgsConstructor` 를 꼭 넣어줘야 한다.\n- Entity 객체 생성 시 아래 애너테이션들은 거의 필수.\n```java\n@NoArgsConstructor // 스프링이 User 객체를 생성할 때 빈 생성자로 new를 하기 때문에 꼭 넣어줘야 한다.\n@Getter\n@EntityListeners(AuditingEntityListener.class)\n@Table(name = \"user_tb\")\n@Entity\n```\n- ServiceTest 시 참고할 어노테이션\n```java\n@Mock // 진짜 객체를 추상화된 가짜 객체로 만들어서 Mockito 환경에 주입한다.    \n@InjectMocks // Mock 된 가까 객체를 진짜 객체인 Service를 만들어서 주입한다.\n@MockBean // Mock 객체들을 스프링 ApplicationContext 에 주입한다. (IoC 컨테이너 주입)\n@Spy // 실제 객체를 만들어서 Mockito 환경에 주입한다.\n@SpyBean // Spy 객체들을 스프링 스프링 ApplicationContext 에 주입한다. (IoC 컨테이너 주입)\n```\n- SpringBootTest 주요 애너테이션 \n```java\n@ActiveProfiles(\"test\") // application-test.yml 설정을 사용한다.\n@AutoConfigureMockMvc // Mockito 환경에서 MockMvc를 사용할 수 있게 해준다.\n@SprintBootTest(webEnvironment = WebEnvironment.MOCK) // 실제로 서버를 띄우지 않고 테스트를 진행할 수 있다.\n```\n- test 에서는 `@Transactional` 애너테이션의 기본 값이 rollback 으로 동작한다. 그래서 테스트가 끝나면 DB에 반영이 안 된다.\n- `@BeforeEach` 로 테스트에 사용할 실제 데이터를 DB에 insert 한다면 클래스 레벨에 `@Transactional` 어노테이션을 붙여서 테스트 후 rollback 되도록 해준다.\n- application.yml 의 `'[org.hibernate.type]': TRACE` : Dynamic Query 의 ? 에 들어가는 값까지 확인할 수 있다.\n- SecurityConfig 작성시 주의사항\n  - 최근 공식문서에 따르면 hasRole() 메서드에 더이상 접두사 \"ROLE_\" 를 붙이지 않는다. 붙이면 오히려 Exception 이 발생한다.\n  - reference : https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html\n```java\nhttp.authorizeRequests()\n    .antMatchers(\"/api/s/**\").authenticated()\n    .antMatchers(\"/api/admin/**\").hasRole(UserEnum.ADMIN.name())\n    .anyRequest().permitAll();\nreturn http.build();\n```\n- 기본적으로 SecurityContext는 TestExecutionListener.beforeTestMethod 이벤트 중에 설정된다. 이는 JUnit의 `@Before` 애너테이션으로 등록한 메서드가 실행되기 이전에 설정된다는 의미이다.\n이를 변경하여 테스트 메서드가 호출되기 전, 즉 JUnit의 `@Before` 이후에 TestExecutionListener.beforeTestExecution 이벤트 중에 발생하도록 할 수 있다.\n- reference : https://docs.spring.io/spring-security/reference/5.7/servlet/test/method.html#test-method-withuserdetails\n```java\n@WithUserDetails(setupBefore = TestExecutionEvent.TEST_EXECUTION)\n```\n- `@Sql(\"classpath:sql/teardown.sql\")` 을 적용하는 이유\n  - 단순히 `@Transsaction` 애너테이션으로 롤백만 해서는 DB에서 auto_increament로 증가되는 id 값들의 초기화가 되지 않아서 테스트가 쌓이다 보면 우리가 원하지 않는 엉뚱한 값이 나올 수 있기 때문에 깔끔하게 초기화를 해준다.\n  - 이때 table 자체를 drop 하게 되면 불필요한 create table 을 하기 때문에 truncate로 데이터만 날린다.\n  - DB와 관련있는 Controller Test를 작성할 때는 아래 4개 애너테이션을 기본적으로 붙이고 시작하자.\n  - `@Sql(\"classpath:db/teardown.sql\")` 애너테이션을 붙여주면 `@BeforeEach` 실행 직전마다 teardown.sql 을 실행한다.\n```java\n@Sql(\"classpath:db/teardown.sql\")\n@ActiveProfiles(\"test\")\n@AutoConfigureMockMvc\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)\n```\n- teardown.sql\n```sql\nSET REFERENTIAL_INTEGRITY FALSE;\ntruncate table transaction_tb;\ntruncate table account_tb;\ntruncate table user_tb;\nSET REFERENTIAL_INTEGRITY TRUE;\n```\n- Service Test에서 stub이 진행될 때 마다 연관된 객체는 새로 만들어서 주입한다. stub1에서 만든 객체를 stub2에서 연결해서 사용하면 타이밍 때문에 값이 꼬인다.\n- `@Valid` 애네테이션을 붙인 객체 바로 뒤에 BindingResult가 없으면 Validation이 되지 않는다. -\u003e `주의` \n\n## Repository Test 시 주의사항\n- Repository 테스트 할 때 더미 데이터를 insert 했따면 꼭 insert 후 `em.clear()` 를 실행하여 Persistence Context를 초기화 해줘야 한다. 그렇지 않으면 영속성 컨텍스트에 캐시된 데이터로 인하여 정확한 테스트가 되지 않는다. Repository Test 에서 필수.\n- Repository 테스트 시 아래 2개 애너테이션을 붙여주고 시작하자\n```java\n@ActiveProfiles(\"test\")\n@DataJpaTest\n```\n- Repository 테스트 시 auto_increment 초기화는 Service 테스트와는 방법이 다르다. 아래 코드와 같이 autoIncrement를 reset 하는 메서드를 만들고 `@BeforeEach`에서 호출하자.\n```java\n@Autowired\nprivate EntityManager em;\n\n@BeforeEach\npublic final void setUp() {\n    autoIncrementReset();\n    dataSetting();\n    em.clear(); // Repository test에서 필수\n    }\n\nprivate void autoIncrementReset() {\n\tem.createNativeQuery(\"ALTER TABLE user_tb ALTER COLUMN id RESTART WITH 1\").executeUpdate();\n\tem.createNativeQuery(\"ALTER TABLE account_tb ALTER COLUMN id RESTART WITH 1\").executeUpdate();\n\tem.createNativeQuery(\"ALTER TABLE transaction_tb ALTER COLUMN id RESTART WITH 1\").executeUpdate();\n}\n```\n- em.clear() 는 DB 관련 테스트에서 필수적으로 넣어야 Persistence Context의 캐시에 의한 오류를 방지할 수 있다.\n## CORS-safelisted response header\n- CORS 허용 목록에 포함된 응답 헤더는 클라이언트 스크립트에 노출해도 안전한 것으로 간주되는 CORS 응답의 HTTP 헤더다.\n- 이 허용 목록에 포함된 응답 헤더만 클라이언트 스크립트(Javascript 등)에서 접근할 수 있다.\n- 클라이언트 스크립트에서 접근 가능한 노출 헤더를 추가하고 싶다면 Security 설정에서 Access-Control-Expose-Headers에 넣어주면 된다.\n- reference : https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header\n- Spring Security 에서는 아래와 같이 설정을 추가해 준다.\n```java\npublic CorsConfigurationSource configurationSource(){\n    ...\n    configuration.addExposedHeader(\"Authorization\");\n    ...\n    return source;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatrixpower1004%2Fspring-security-bankapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatrixpower1004%2Fspring-security-bankapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatrixpower1004%2Fspring-security-bankapp/lists"}