Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package cmf.commitField.domain.user.controller;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class AuthController {
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
return principal.getAttributes(); // ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ˜ํ™˜

@GetMapping("/login")
public ResponseEntity<?> user() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if (authentication instanceof OAuth2AuthenticationToken) {
OAuth2User principal = (OAuth2User) authentication.getPrincipal();
return ResponseEntity.ok(principal.getAttributes()); // ์‚ฌ์šฉ์ž ์ •๋ณด ๋ฐ˜ํ™˜
}

return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.");
}
}
}
69 changes: 69 additions & 0 deletions src/main/java/cmf/commitField/global/security/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package cmf.commitField.global.security;

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.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
protected SecurityFilterChain config(HttpSecurity http) throws Exception {

//๋กœ๊ทธ์ธ ๊ด€๋ จ ์„ค์ •
http
.oauth2Login(oauth2 -> oauth2
.loginPage("/login") // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ์ง€์ •
.successHandler((request, response, authentication) -> {
// ์ธ์ฆ ์ •๋ณด๊ฐ€ SecurityContext์— ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅ
SecurityContextHolder.getContext().setAuthentication(authentication);

// ๋””๋ฒ„๊น…: authentication ์ •๋ณด ํ™•์ธ
System.out.println("Authentication: " + authentication);
System.out.println("Principal: " + authentication.getPrincipal());

if (authentication != null && authentication.getPrincipal() != null) {
//์ธ๊ฐ€๊ฐ€ ์žˆ์œผ๋ฉด ์œ ์ € ์ •๋ณด๋ฅผ ์ €์žฅ
OAuth2User principal = (OAuth2User) authentication.getPrincipal();
String username = principal.getAttribute("login");

// ์„ธ์…˜์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ถ”๊ฐ€
request.getSession().setAttribute("user", username);

response.sendRedirect("/"); // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
} else {
// ์ธ์ฆ ์‹คํŒจ ์‹œ ์ฒ˜๋ฆฌ
response.sendRedirect("/login?error=authenticationFailed");
}
})
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // ์„ธ์…˜ ์ •์ฑ… ์„ค์ •
.invalidSessionUrl("/login?error=invalidSession") // ์„ธ์…˜์ด ์œ ํšจํ•˜์ง€ ์•Š์œผ๋ฉด ์ด๋™ํ•  URL
.maximumSessions(1) // ํ•˜๋‚˜์˜ ๊ณ„์ •์œผ๋กœ ํ•œ ๋ฒˆ์— ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œํ•œ
.expiredUrl("/login?error=sessionExpired") // ์„ธ์…˜ ๋งŒ๋ฃŒ ํ›„ ์ด๋™ํ•  URL ์„ค์ •
);

//๋กœ๊ทธ์•„์›ƒ ๊ด€๋ จ ์„ค์ •
http
.logout(logout -> logout
.logoutUrl("/logout") // ๋กœ๊ทธ์•„์›ƒ URL ์„ค์ •
.logoutSuccessUrl("/") // ๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต ํ›„ ์ด๋™ํ•  URL
.invalidateHttpSession(true) // ๋กœ๊ทธ์•„์›ƒ ์‹œ ์„ธ์…˜ ๋ฌดํšจํ™”
.clearAuthentication(true) // ์ธ์ฆ ์ •๋ณด ์ง€์šฐ๊ธฐ
.deleteCookies("JSESSIONID") // ์„ธ์…˜ ์ฟ ํ‚ค ์‚ญ์ œ
);
http
.csrf(
AbstractHttpConfigurer::disable // CSRF ๋ณดํ˜ธ ๋น„ํ™œ์„ฑํ™”
);

return http.build();
}
}
4 changes: 2 additions & 2 deletions src/main/resources/application-secret.yml.default
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ custom:
spring:
data:
redis:
password: cmf123414
key: cmf123414
password: NEED_TO_INPUT
key: NEED_TO_INPUT
spring:
security:
oauth2:
Expand Down
Binary file added src/main/resources/static/favicon.ico
Binary file not shown.
47 changes: 47 additions & 0 deletions src/main/resources/static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GitHub OAuth2 ๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ</title>
</head>
<body>
<h1>GitHub OAuth2 ๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ</h1>

<!-- ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ -->
<a href="/oauth2/authorization/github" id="loginBtn" style="display: none;">
<button>GitHub ๋กœ๊ทธ์ธ</button>
</a>

<!-- ๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ -->
<button id="logoutBtn" style="display: none;">๋กœ๊ทธ์•„์›ƒ</button>

<h2>์‚ฌ์šฉ์ž ์ •๋ณด</h2>
<pre id="userInfo">๋กœ๊ทธ์ธ ํ›„ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค...</pre>

<script>
async function fetchUser() {
try {
const response = await fetch('/login');
if (!response.ok) throw new Error("Not logged in");

const data = await response.json();
document.getElementById("userInfo").textContent = JSON.stringify(data, null, 2);
document.getElementById("logoutBtn").style.display = "block";
document.getElementById("loginBtn").style.display = "none";
} catch (error) {
document.getElementById("userInfo").textContent = "๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.";
document.getElementById("logoutBtn").style.display = "none";
document.getElementById("loginBtn").style.display = "inline-block";
}
}

document.getElementById("logoutBtn").addEventListener("click", async () => {
await fetch('/logout', { method: 'POST' }); // POST ๋ฐฉ์‹์œผ๋กœ ๋กœ๊ทธ์•„์›ƒ
fetchUser(); // ๋กœ๊ทธ์•„์›ƒ ํ›„ ์‚ฌ์šฉ์ž ์ •๋ณด ๊ฐฑ์‹ 
});

fetchUser(); // ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ ์‚ฌ์šฉ์ž ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ
</script>
</body>
</html>