개발환경
MySQL 회원 테이블 생성
프로젝트 생성
New Spring Starter Project
New Spring Starter Dependencies
기본 설정 및 OAuth2 변수 설정
application.yml 설정
Spring Security 설정
SecurityConfig 구현
프론트 페이지 생성
메인 페이지
Entity 추가
프로젝트 구조
개발 환경 | 버전 |
---|---|
Java | 17 |
Spring Boot | 3.2.7 |
Spring Security | 6.2.5 |
Spring Security OAuth2 Client | 6.2.5 |
Spring Data JPA | 3.2.7 |
Lombok | 1.18.30 |
빌드 관리 도구 | Gradle 8.8 |
템플릿 엔진 | Mustache |
DB | MySQL 8.0.36 |
개발 도구 | Spring Tool Suite 4.22.1 |
CREATE TABLE `members` (
`ID` int NOT NULL AUTO_INCREMENT COMMENT '고유번호',
`USERID` varchar(65) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '아이디',
`USERNAME` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '이름',
`EMAIL` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '이메일 주소',
`ROLE` varchar(9) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '권한',
`PROVIDER` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '공급자',
`PROVIDER_ID` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '공급자 고유 ID',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Spring Boot Version 3.2.7 선택합니다.
검색란에 의존성 키워드를 입력하여 의존성을 추가합니다. (녹색 영역 참조)
application.properties파일의 확장자를 application.yml 확장자로 변경합니다.
spring:
application:
name: oauth2
server:
port: 8080
servlet:
session:
timeout: 3600 #세션 유지시간 설정
encoding:
force: true #mustache UTF-8
---
#mustache 설정
spring:
mustache:
cache: false
servlet:
expose-request-attributes: true #mustache에서 csrf 토큰 변수 오류 발생 때문에 추가
expose-session-attributes: true #세션
---
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/work?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
username: user03
password: localdbpass!
jpa:
properties:
hibernate:
format_sql: true #JPA 쿼리문 정렬된 형태로 출력
# JPA 쿼리문, binding parameter 출력
logging:
level:
org:
hibernate:
SQL: TRACE
orm:
jdbc:
bind: TRACE
---
#OAuth2 변수 설정
spring:
security:
oauth2:
client:
registration:
google:
client-id: 858221476598-nrp6n72ecrmkhfj2r7qoqbd85t0up6c8.apps.googleusercontent.com
client-secret: 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
redirect-uri: http://localhost:8080/login/oauth2/code/google
authorization-grant-type: authorization_code
scope:
- profile
- email
naver:
client-name: naver
client-id: 89eb6tH0NecXpm5n4Cna
client-secret: G7X7ltb1UI
redirect-uri: http://localhost:8080/login/oauth2/code/naver
authorization-grant-type: authorization_code
scope:
- name
- email
provider:
naver:
authorization-uri: https://nid.naver.com/oauth2.0/authorize
token-uri: https://nid.naver.com/oauth2.0/token
user-info-uri: https://openapi.naver.com/v1/nid/me
user-name-attribute: response
config 패키지를 생성 후 SecurityConfig 클래스 파일을 생성합니다.
패키지 위치 : com.example.oauth2.config
package com.example.oauth2.config;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
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.web.SecurityFilterChain;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// csrf token
http
.csrf((csrf) -> csrf.disable()); // 비활성화
// 인가
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources의 static(정적파일) 모두 허용
.requestMatchers("/", "/login", "/login/oauth2/code/*").permitAll() // 보안 검사 없이 접근을 허용
//.requestMatchers("/member/**").hasAnyRole("ADMIN", "USER") // role - ADMIN, USER만 접근 허용
//.requestMatchers("/admin").hasRole("ADMIN") // role - ADMIN만 접근 허용
.anyRequest().authenticated()
);
return http.build();
}
}
controller 패키지를 생성 후 MainController 클래스 파일을 생성합니다.
패키지 위치 : com.example.oauth2.controller
package com.example.oauth2.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
/**
* 메인 페이지
* @return
*/
@GetMapping("/")
public String index() {
return "index";
}
}
templates에 index.mustache 파일을 생성합니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>메인 페이지</title>
<style>
.container {
width: 800px !important ;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12 pt-5">
<div class="card mb-4">
<h5 class="card-header text-center">메인 페이지</h5>
<div class="card-body">
{{#isLogin}}
<h5 class="card-title">{{username}}님 환영합니다.</h5>
<p class="card-text">접속하신 아이디는 {{userid}} 입니다.</p>
{{/isLogin}}
{{^isLogin}}
<div class="col-md-12 text-center">
<a href="/login" class="btn btn-outline-success">로그인</a>
</div>
{{/isLogin}}
</div>
</div>
</div>
</div>
{{#isLogin}}
<div class="row">
<div class="col-md-12 text-center">
<a href="/logout" class="btn btn-outline-danger">로그아웃</a>
</div>
</div>
{{/isLogin}}
</div>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
entity 패키지를 생성 후 Members 클래스 파일을 생성합니다.
패키지 위치 : com.example.oauth2.entity
package com.example.oauth2.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Getter
@Entity
public class Members {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 아이디
@Column(nullable = false)
private String userid; // Spring Security username
// 이메일 주소
@Column(nullable = false)
private String email;
// 이름
@Column(nullable = false)
private String username; // 만일 null값이 들어올 경우 예외처리 필요
// 권한
@Column(nullable = false)
private String role;
// 공급자
@Column(nullable = false)
private String provider;
// 공급자 고유 ID
@Column(nullable = false)
private String providerId;
@Builder
public Members(String userid, String email, String username, String role, String provider, String providerId) {
this.userid = userid;
this.email = email;
this.username = username;
this.role = role;
this.provider = provider;
this.providerId = providerId;
}
}
OAuth2 Login | |
---|---|
2024.07.18 | [Spring Security] OAuth2 구글, 네이버 로그인 구현하기 (4) |
2024.07.17 | [Spring Security] OAuth2 구글, 네이버 로그인 구현하기 (3) |
2024.07.15 | [Spring Security] OAuth2 구글, 네이버 로그인 구현하기 (2) |
2024.07.15 | [Spring Security] OAuth2 구글, 네이버 로그인 구현하기 (1) |