์นด์นด์ค ๋ก๊ทธ์ธ ๊ธฐ๋ณธ ํ๋ก์ ํธ
ํ๋ก์ ํธ ๋ชฉํ
Spring Security, OAuth2 Client ์์กด์ฑ์ ์ฌ์ฉํ์ฌ, ๋จ์ํ OAuth ์ธ์ฆ ์ค์ ์ ํตํด ์นด์นด์ค ๋ก๊ทธ์ธ์ ๊ตฌํ
Code
Preview
3.
์์ ํ๋ก์ธ์ค
Preview
๋ฉ์ธ ํ๋ฉด
๋ก๊ทธ์ธ ํ๋ฉด
๋ก๊ทธ์ธ
1.
์นด์นด์ค ๋ก๊ทธ์ธ
2.
2๋จ๊ณ ์ธ์ฆ
์นด์นด์ค ๋ก๊ทธ์ธ
2๋จ๊ณ ์ธ์ฆ
๋ฉ์ธ ํ๋ฉด (๋ก๊ทธ์ธ ์๋ฃ)
์์ ํ๋ก์ธ์ค
1.
ํ๋ก์ ํธ ์์ฑ
โข
โข
spring boot version : 2.x.x
โข
spring security version : 5.x.x
โข
์์กด์ฑ ์ค์
โฆ
Spring Web
โฆ
Spring Boot DevTools
โฆ
Spring Security
โฆ
OAuth2 Client
โฆ
Lombok
โฆ
Thymeleaf
2.
ํ๋ก์ ํธ ์ค์
โข
profile ํ์ผ ์์ฑํ๊ธฐ
โฆ
โข
profile ํ์ผ ํฌํจํ๊ธฐ
โฆ
spring.profiles.include=oauth
Plain Text
๋ณต์ฌ
3.
์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
โข
4.
์์ฒญ ๊ฒฝ๋ก ๋งคํ
โข
โฆ
๋ฉ์ธ ํ๋ฉด
โช
โช
ํ๋ก์ ํธ ์์ฑ
1.
ํ๋ก์ ํธ ์์ฑ
2.
ํ๋ก์ ํธ ์ค์
3.
์์กด์ฑ ์ค์
4.
build.gradle
๋ช ๋ น ํ๋ ํธ [ctrl + shift + P]
Create a gradle Project ์ ๋ ฅ
ํ๋ก์ ํธ ์ค์
1.
Spring Boot Version
2.
Language
3.
Group Id
4.
Artifact Id
5.
packaging type
6.
Java version
Spring Boot Version
Language
Group Id
Artifact Id
packaging type
Java version
์์กด์ฑ ์ค์
1.
Spring Web
2.
Spring boot devtools
3.
Lombok
4.
Thymeleaf
5.
Spring Security
6.
OAuth2 Client
Spring Web
Spring boot devtools
Lombok
Thymeleaf
Spring Security
OAuth2 Client
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '2.7.17'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'com.aloha'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
Java
๋ณต์ฌ
ํ๋ก์ ํธ ์ค์
โข
profile ํ์ผ ์์ฑํ๊ธฐ
โฆ
โข
profile ํ์ผ ํฌํจํ๊ธฐ
โฆ
spring.profiles.include=oauth
Plain Text
๋ณต์ฌ
profile ํ์ผ ์์ฑํ๊ธฐ
Kakao Devleoper ์ฌ์ดํธ์์ ์ฑ ์ค์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
์ ํ์ด์ง์์ ์นด์นด์ค ์ฌ์ดํธ์์ ์ ํ๋ฆฌ์ผ์ด์
์ถ๊ฐ ๋ฐ ์ค์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ด์ฉ์ ๋ํ์ฌ ๋ค๋ฃน๋๋ค.
application-oauth.properties
#Kakao OAuth Settings
# client-id : REST API KEY
spring.security.oauth2.client.registration.kakao.client-id=[REST API KEY]
# client-secret : ๋ด ์ ํ๋ฆฌ์ผ์ด์
> ๋ณด์ > Client secret
spring.security.oauth2.client.registration.kakao.client-secret=[Client Secret]
# redirect-uri : ์ฌ์ฉ์๊ฐ ์นด์นด์ค๋ก ๋ก๊ทธ์ธ ํ ๋์์ฌ ์๋ฒ์ URL
spring.security.oauth2.client.registration.kakao.redirect-uri=http://localhost:8080/login/oauth2/code/kakao
# authorization-grant-type : ์ก์ธ์ค ํ ํฐ ์์ฒญ ์, ์ ํ์ ์ง์ ํ๋ ํค๋ ์์ฑ
spring.security.oauth2.client.registration.kakao.authorization-grant-type=authorization_code
# scope : ์ฌ์ฉ์ ์ ๋ณด ์์ฒญ ๋ฒ์๋ฅผ ์ง์ ํ๋ ์์ฑ
# โ
biz ๊ณ์ (์ฌ์
์๋ฑ๋ก๋ฒํธ)์ผ ๊ฒฝ์ฐ์๋ง email ์์ฒญ์ด ๊ฐ๋ฅ
# spring.security.oauth2.client.registration.kakao.scope=profile_nickname, account_email, profile_image
spring.security.oauth2.client.registration.kakao.scope=profile_nickname, profile_image
# client-name : ํด๋ผ์ด์ธํธ๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํ ์ด๋ฆ
spring.security.oauth2.client.registration.kakao.client-name=Kakao
# client-authentication-method : ์ธ์ฆ ์๋ฒ๋ก ์์ฒญ ์, ์ง์ ํ ์์ฒญ ๋ฉ์๋
spring.security.oauth2.client.registration.kakao.client-authentication-method=POST
# authorization-uri : ์ธ๊ฐ ์ฝ๋ ์์ฒญ URI (์ธ์ฆ ์๋ฒ)
spring.security.oauth2.client.provider.kakao.authorization-uri=https://kauth.kakao.com/oauth/authorize
# token-uri : ์ก์ธ์ค ํ ํฐ ์์ฒญ URI (์ธ์ฆ ์๋ฒ)
spring.security.oauth2.client.provider.kakao.token-uri=https://kauth.kakao.com/oauth/token
# user-info-uri : ์ฌ์ฉ์ ์ ๋ณด ์์ฒญ URI (๋ฆฌ์์ค ์๋ฒ)
spring.security.oauth2.client.provider.kakao.user-info-uri=https://kapi.kakao.com/v2/user/me
# user-name-attribute : ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ณ ์ ์๋ณ๊ฐ ํค ์์ฑ
spring.security.oauth2.client.provider.kakao.user-name-attribute=id
Java
๋ณต์ฌ
profile ํ์ผ ํฌํจํ๊ธฐ
application.properties
spring.application.name=kakao
# application-oauth.propeties ํ์ผ ํฌํจํ๊ธฐ
spring.profiles.include=oauth
Java
๋ณต์ฌ
application-[ํ๋กํ๋ช
].properties ํํ๋ก ํ๋กํ ํ์ผ์ ์์ฑํ๋ฉด,
application.properties ํ์ผ์์ spring.profiles.include ์์ฑ์ผ๋ก ํ๋กํ๋ช
์ ์ง์ ํ์ฌ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค.
์คํ๋ง ์ํ๋ฆฌํฐ ์ค์
~/config/SecurityConfig.java
@EnableWebSecurity
@Configuration
public class SecurityConfig {
/**
* ๐ ์คํ๋ง ์ํ๋ฆฌํฐ ์ค์ ๋ฉ์๋
* @param http
* @return
* @throws Exception
*/
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// ๐ฉโ๐ผ ์ธ๊ฐ ์ค์
http.authorizeRequests(requests -> requests
.antMatchers("/").permitAll()
.anyRequest().authenticated());
// ๐ฉโ๐ป๐ OAuth2 ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ํ์ฑํ
http.oauth2Login(withDefaults());
return http.build();
}
}
Java
๋ณต์ฌ
์์ฒญ ๊ฒฝ๋ก ๋งคํ
~/controller/HomeController.java
โข
๋ฉ์ธ ํ๋ฉด
โฆ
โฆ
HomeController.java
@Slf4j
@Controller
public class HomeController {
/**
* ๋ฉ์ธ ํ๋ฉด
* ๐ [GET] - /
* ๐ index.html
* @return
*/
@GetMapping("/")
public String home() {
log.info(":::::::::: ๋ฉ์ธ ํ๋ฉด ::::::::::");
return "/index";
}
}
Java
๋ณต์ฌ
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OAuth</title>
<!-- bootstrap css -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container col-10 col-lg-4">
<div class="px-4 py-5 mt-5 text-center">
<h1 class="display-5 fw-bold text-body-emphasis">๋ฉ์ธ ํ๋ฉด</h1>
</div>
<!-- ๋น ๋ก๊ทธ์ธ ์ -->
<th:block sec:authorize="isAnonymous()">
<div class="d-grid gap-2">
<a href="/login" class="btn btn-lg btn-primary">๋ก๊ทธ์ธ</a>
</div>
</th:block>
<!-- ๋ก๊ทธ์ธ ์ -->
<th:block sec:authorize="isAuthenticated()">
<div class="card">
<div class="inner p-4">
<div class="d-flex flex-column align-items-center">
<div class="item my-2 w-100">
<span sec:authentication="principal">์์ด๋</span>
</div>
</div>
</div>
</div>
<form action="/logout" method="post">
<!-- CSRF TOKEN -->
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<div class="d-grid gap-2">
<button type="submit" class="btn btn-lg btn-primary">๋ก๊ทธ์์</button>
</div>
</form>
</th:block>
</div>
<!-- bootstrap js -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
HTML
๋ณต์ฌ