Skip to content

Conversation

@minjee2758
Copy link
Collaborator

@minjee2758 minjee2758 commented Jul 20, 2025

문제 상황

/api/problems & /api/problems/{problemId} 경로 접근에 문제 발생

현 상황

이 경로가 PUBLIC_PATH에 포함되어있음
문제 목록(GET)은 가능함

문제 발생

문제 제출(POST) 불가능
"로그인 후 이용 가능합니다" 예외 대신 "토큰이 필요합니다"라는 메시지가 반환
-> JWT 필터 그냥 넘어가지니까 (인증되지 않은 상태) 제출 로직에서 인증이 필요하여 발생

해결 방법

Spring Security의 authorizeHttpRequests 설정에서 경로별 HTTP 메서드를 구분
(요청마다 인증이 필요한거 없는거 나누기)

                .requestMatchers(SecurityPath.PUBLIC_PATH).permitAll() --> 퍼블릭으로 설정된 애들은  통과

                // 문제에서 GET은 별도 인증없이 볼 수 있음 
                .requestMatchers(HttpMethod.GET, "/api/problems", "/api/problems/{problemId}").permitAll()
                
               // GET을 제외한 모든 /api/problems/** 요청은 JWT 필터를 거쳐 유효한 토큰이 있어야만 접근 가능
                .requestMatchers("/api/problems/**").authenticated() 

               // 아래는 기존과 동일 
                .requestMatchers("/api/admin/**").hasRole("ADMIN") //어드민 권한 필요 (문제 생성, 관리 등)
                .requestMatchers(HttpMethod.GET,
                   "/api/languages",
                   "/api/problems/*/discussions",
                   "/api/problems/{problemId}/discussions/{discussionId}/replies",
                   "/api/problems/{problemId}/discussions/{discussionId}/replies/**").permitAll()
                .anyRequest().authenticated() //나머지는 일반 인증

코드 리뷰 전 확인 체크리스트

  • 불필요한 콘솔 로그, 주석 제거
  • 커밋 메시지 컨벤션 준수 (type : )
  • 기능 정상 동작 확인

Summary by CodeRabbit

  • 신규 기능

    • 비밀번호 재설정 페이지가 추가되어, 사용자가 새 비밀번호를 입력하고 재설정할 수 있습니다.
    • 비밀번호 재설정 성공 시 안내 모달이 표시되고, 2초 후 로그인 페이지로 이동합니다.
  • 버그 수정

    • 프로필 이미지가 더 이상 자동으로 업데이트되지 않도록 수정되었습니다.
  • 스타일

    • 모달 다이얼로그와 비밀번호 재설정 페이지에 어울리는 새로운 CSS 스타일이 추가되었습니다.
  • 접근 제어

    • 문제 목록 및 상세 조회(GET 요청)는 인증 없이 접근 가능하지만, 그 외 문제 관련 요청(POST, PUT, DELETE 등)은 인증이 필요하도록 보안 규칙이 강화되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Jul 20, 2025

Walkthrough

HTTP 보안 설정이 /api/problems 엔드포인트에 대해 HTTP 메서드별로 세분화되어, GET 요청만 비인증 접근이 허용되고 그 외 메서드는 인증이 필요하도록 변경되었습니다. 추가로, 비밀번호 재설정 뷰와 관련된 HTML, CSS, 컨트롤러, JavaScript 파일이 새로 추가 및 수정되었습니다.

Changes

파일/경로 요약 변경 내용 요약
.../security/config/SecurityConfig.java, .../security/util/SecurityPath.java /api/problems/** 경로의 공개 접근을 제거하고, GET만 비인증 허용, 나머지 메서드는 인증 필요로 변경
.../presentation/view/ViewController.java 비밀번호 재설정 페이지(/test/reset-password)용 GET 엔드포인트 추가
.../static/css/test-login.css 모달 다이얼로그 스타일 등 신규 CSS 추가
.../static/js/test-mypage.js, .../templates/test-mypage.html 프로필 이미지 관련 렌더링 코드와 id 속성 제거
.../templates/test-reset-password.html 비밀번호 재설정용 신규 HTML 템플릿 및 JS 로직 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant Backend
    participant DB

    User->>Browser: /test/reset-password 접속
    Browser->>Backend: GET /test/reset-password
    Backend-->>Browser: test-reset-password.html 반환
    User->>Browser: 새 비밀번호 입력 및 제출
    Browser->>Backend: POST /api/auth/reset-password (token, 비밀번호)
    Backend->>DB: 토큰 및 비밀번호 검증/저장
    DB-->>Backend: 결과 반환
    Backend-->>Browser: 성공/실패 응답
    Browser-->>User: 성공 시 모달 표시 및 로그인 페이지로 리다이렉트
Loading

Possibly related PRs

Suggested labels

enhancement, bug

Suggested reviewers

  • pokerbearkr
  • NCookies

Poem

🐰
보안의 문을 한 번 더 잠그고,
GET만 살짝 열어두었죠.
비밀번호 재설정 뷰도 새로 생겼네,
어두운 모달 속에 희망이 반짝!
토끼는 오늘도 코드를 다듬으며
안전한 세상을 꿈꿔요.
🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/main/java/org/ezcode/codetest/presentation/view/ViewController.java (1)

23-26: 새 뷰 매핑은 좋지만 상수화·공통 prefix 사용을 고려하세요.

"/test/reset-password" 경로가 하드코딩되어 있습니다. 다른 테스트용 뷰들과 동일하게 /test/** 패턴을 많이 사용하고 있지만, 추후 운영/테스트 분리가 필요할 때 유지‧변경 비용이 커질 수 있습니다.

  • public static final String TEST_PREFIX = "/test"; 같은 상수를 두고 TEST_PREFIX + "/reset-password" 형태로 지정하면 경로를 한곳에서 관리할 수 있습니다.
  • 혹은 @RequestMapping("/test")를 클래스 레벨에 선언해 중복을 제거하세요.
src/main/resources/templates/test-reset-password.html (2)

144-149: 토글 함수가 실제 UI와 연결되지 않음

toggleVisibility()는 정의만 있고 호출이 없습니다.
아이콘(🔒) 우측에 눈 아이콘을 추가해 클릭 시 호출하도록 하거나, 사용하지 않을 예정이라면 코드를 제거해 주세요. 사용하지 않는 dead-code 는 유지보수 비용만 증가시킵니다.


172-180: 비밀번호 복잡도·길이 검증 없음

클라이언트에서 최소 길이(예: 8자)·대소문자·숫자 조합 등을 1차로 확인해주면 불필요한 서버 round-trip을 줄일 수 있습니다.

if (newPassword.length < 8) {
  alert("비밀번호는 최소 8자 이상이어야 합니다.");
  return;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06fc7ab and ae81469.

⛔ Files ignored due to path filters (6)
  • .DS_Store is excluded by !**/.DS_Store
  • src/.DS_Store is excluded by !**/.DS_Store
  • src/main/.DS_Store is excluded by !**/.DS_Store
  • src/main/java/.DS_Store is excluded by !**/.DS_Store
  • src/main/java/org/.DS_Store is excluded by !**/.DS_Store
  • src/main/resources/static/images/lock-icon.png is excluded by !**/*.png
📒 Files selected for processing (7)
  • src/main/java/org/ezcode/codetest/common/security/config/SecurityConfig.java (1 hunks)
  • src/main/java/org/ezcode/codetest/common/security/util/SecurityPath.java (1 hunks)
  • src/main/java/org/ezcode/codetest/presentation/view/ViewController.java (1 hunks)
  • src/main/resources/static/css/test-login.css (1 hunks)
  • src/main/resources/static/js/test-mypage.js (1 hunks)
  • src/main/resources/templates/test-mypage.html (1 hunks)
  • src/main/resources/templates/test-reset-password.html (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: NCookies
PR: ezcode-my/backend#17
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/ProblemAdminController.java:25-25
Timestamp: 2025-06-02T06:57:37.929Z
Learning: 이 프로젝트에서는 아직 Spring Security가 적용되지 않아서 @PreAuthorize 어노테이션이 주석 처리되어 있음. Spring Security 도입 전까지는 권한 검증 어노테이션들이 비활성화 상태임.
Learnt from: minjee2758
PR: ezcode-my/backend#9
File: src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java:32-39
Timestamp: 2025-05-31T11:26:06.360Z
Learning: AuthService.signin() 메서드에서 userPasswordCheck 호출 시 signinRequest.getPassword() (원본 비밀번호)를 전달해야 하는데, loginUser.getPassword() (해시된 비밀번호)를 전달하는 버그가 있었음.
src/main/java/org/ezcode/codetest/common/security/config/SecurityConfig.java (1)
Learnt from: NCookies
PR: ezcode-my/backend#17
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/ProblemAdminController.java:25-25
Timestamp: 2025-06-02T06:57:37.929Z
Learning: 이 프로젝트에서는 아직 Spring Security가 적용되지 않아서 @PreAuthorize 어노테이션이 주석 처리되어 있음. Spring Security 도입 전까지는 권한 검증 어노테이션들이 비활성화 상태임.
src/main/resources/templates/test-reset-password.html (2)
Learnt from: thezz9
PR: ezcode-my/backend#73
File: src/main/resources/templates/submit-test.html:135-135
Timestamp: 2025-06-18T11:41:58.457Z
Learning: src/main/resources/templates/submit-test.html 파일은 테스트용 파일로, isCorrect 값의 하드코딩은 의도적이며 사용자가 UI 요소를 통해 정답/오답 상태를 선택할 수 있도록 개선 예정입니다.
Learnt from: minjee2758
PR: ezcode-my/backend#9
File: src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java:32-39
Timestamp: 2025-05-31T11:26:06.360Z
Learning: AuthService.signin() 메서드에서 userPasswordCheck 호출 시 signinRequest.getPassword() (원본 비밀번호)를 전달해야 하는데, loginUser.getPassword() (해시된 비밀번호)를 전달하는 버그가 있었음.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (6)
src/main/java/org/ezcode/codetest/common/security/util/SecurityPath.java (1)

20-20: 변경사항이 적절합니다.

/api/problems/** 경로를 공개 경로에서 제거하고 SecurityConfig에서 HTTP 메서드별로 세분화하여 처리하는 것이 PR 목표와 일치합니다. 주석을 통해 변경 이유도 명확히 설명되어 있습니다.

src/main/resources/static/css/test-login.css (1)

214-284: 모달 스타일이 잘 구현되었습니다.

새로 추가된 모달 스타일이 기존 디자인 시스템과 일관성을 유지하고 있으며, 사용자 경험을 고려한 호버 효과와 적절한 색상 조합이 적용되었습니다.

src/main/java/org/ezcode/codetest/common/security/config/SecurityConfig.java (1)

79-81: HTTP 메서드별 접근 제어가 올바르게 구현되었습니다.

GET 요청은 비인증 접근을 허용하고, 나머지 HTTP 메서드는 인증을 요구하도록 세분화된 설정이 PR 목표와 정확히 일치합니다. Spring Security 규칙의 순서도 올바르게 구성되어 있습니다.

src/main/resources/templates/test-mypage.html (1)

30-30: 프로필 이미지 기능 비활성화에 대한 확인이 필요합니다.

img 태그에서 id="profileImage" 속성이 제거되었고, 연관된 JavaScript에서도 동적 업데이트가 비활성화되었습니다. 이것이 임시적인 변경인지 영구적인 기능 제거인지 확인이 필요하며, 사용자의 프로필 이미지 관리 기능에 미치는 영향을 검토해야 합니다.

src/main/resources/static/js/test-mypage.js (1)

59-59: 프로필 이미지 기능 주석 처리에 대한 명확화가 필요합니다.

HTML 템플릿의 변경사항과 일관성 있게 프로필 이미지 업데이트 기능이 비활성화되었습니다. 하지만 주석 처리된 코드를 유지할 것인지, 완전히 제거할 것인지 결정이 필요하며, 사용자 데이터의 profileImageUrl 필드 활용 계획도 명확히 해야 합니다.

src/main/resources/templates/test-reset-password.html (1)

195-200: response.json() 두 번 호출 가능성

에러 처리에서 이미 await response.json()으로 스트림을 소비했으므로, 이후 성공 경로에서도 await response.json()을 다시 호출하면 스트림이 비어 있어 예외가 날 수 있습니다. 한 번만 파싱하거나 clone()을 사용하세요.

- const result = await response.json();
+ const result = await response.clone().json();

또는 성공·실패 분기 전에 한 번만 파싱하도록 구조를 바꾸는 것이 명확합니다.

Comment on lines +156 to +164
const modalHtml = `
<div id="success-modal" class="modal" style="display: flex; align-items: center; justify-content: center;">
<div class="modal-content">
<h3>완료</h3>
<p>${message}</p>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', modalHtml);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

XSS 취약점: 서버 메시지를 그대로 innerHTML 삽입

${message}가 escape 없이 모달에 삽입되어 있습니다. 악의적인 스크립트가 포함될 경우 클라이언트에서 실행될 수 있습니다.

- <p>${message}</p>
+ <p id="reset-msg"></p>

그리고 JS 쪽에서:

- showSuccessModal(result.message || "비밀번호가 성공적으로 변경되었습니다.");
+ showSuccessModal(result.message ?? "비밀번호가 성공적으로 변경되었습니다.");

function showSuccessModal(message) {
  const modalHtml = `
    <div id="success-modal" class="modal" style="display:flex;align-items:center;justify-content:center;">
      <div class="modal-content">
        <h3>완료</h3>
        <p id="reset-msg"></p>
      </div>
    </div>`;
  document.body.insertAdjacentHTML('beforeend', modalHtml);
  document.getElementById('reset-msg').textContent = message; // textContent 로 XSS 차단
}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/resources/templates/test-reset-password.html around lines 156 to
164, the code inserts the server-provided message directly into the modal's
innerHTML without escaping, causing an XSS vulnerability. To fix this, sanitize
or escape the message content before inserting it into the HTML, or use
textContent assignment instead of innerHTML to safely display the message
without executing any embedded scripts.

@pokerbearkr pokerbearkr merged commit b55eb66 into dev Jul 22, 2025
2 checks passed
@pokerbearkr pokerbearkr deleted the refactor/security-path branch July 22, 2025 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants