Skip to content

Commit

Permalink
Merge branch 'feat/kookmin-sw#2-OAuthNaver' of https://github.com/cap…
Browse files Browse the repository at this point in the history
  • Loading branch information
leejh7 committed Mar 10, 2024
2 parents ebf2d45 + a349d85 commit f2beff6
Show file tree
Hide file tree
Showing 24 changed files with 1,195 additions and 1 deletion.
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'

// spring security 설정
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

// OAuth 2.0 설정
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
}

tasks.named('test') {
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/org/capstone/maru/config/JpaConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.capstone.maru.config;

import java.util.Optional;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@Configuration
public class JpaConfig {

@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.of("tester");
}
}
101 changes: 101 additions & 0 deletions src/main/java/org/capstone/maru/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package org.capstone.maru.config;


import lombok.extern.slf4j.Slf4j;
import org.capstone.maru.dto.security.KakaoOAuth2Response;
import org.capstone.maru.dto.security.SharedPostPrincipal;
import org.capstone.maru.service.MemberAccountService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.SecurityFilterChain;

@Slf4j
@Configuration
public class SecurityConfig {

@Bean
@ConditionalOnProperty(name = "spring.h2.console.enabled", havingValue = "true")
public WebSecurityCustomizer configureH2ConsoleEnable() {
return web -> web.ignoring()
.requestMatchers(PathRequest.toH2Console());
}

@Bean
public SecurityFilterChain securityFilterChain(
HttpSecurity httpSecurity,
OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService
) throws Exception {
log.info("SecurityFilterChain 빈 등록 완료");
return httpSecurity
.authorizeHttpRequests(auth -> auth
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.requestMatchers(
HttpMethod.GET,
"/"
).permitAll()
.anyRequest().authenticated()
)
.oauth2Login(oAuth -> oAuth
.userInfoEndpoint(userInfo -> userInfo
.userService(oAuth2UserService)
)
)
.csrf(
csrf -> csrf
.ignoringRequestMatchers("/api/**")
.disable()
)
.build();
}


@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService(
MemberAccountService memberAccountService,
PasswordEncoder passwordEncoder
) {
final DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();

return userRequest -> {
OAuth2User oAuth2User = delegate.loadUser(userRequest);

KakaoOAuth2Response kakaoOAuthResponse = KakaoOAuth2Response.from(
oAuth2User.getAttributes());

String registrationId = userRequest.getClientRegistration()
.getRegistrationId(); // "kakao"

String providerId = String.valueOf(kakaoOAuthResponse.id());
String memberId = registrationId + "_" + providerId;

return memberAccountService
.searchMember(memberId)
.map(SharedPostPrincipal::from)
.orElseGet(() ->
SharedPostPrincipal.from(
memberAccountService.saveUser(
memberId,
kakaoOAuthResponse.email(),
kakaoOAuthResponse.nickname()
)
)
);
};
}

@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
21 changes: 21 additions & 0 deletions src/main/java/org/capstone/maru/controller/MainController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.capstone.maru.controller;

import org.capstone.maru.dto.security.SharedPostPrincipal;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainController {

@GetMapping("/")
public String root() {
return "home";
}

@GetMapping("/test")
public String test(@AuthenticationPrincipal SharedPostPrincipal sharedPostPrincipal) {
return sharedPostPrincipal.getName();
}

}
39 changes: 39 additions & 0 deletions src/main/java/org/capstone/maru/domain/AuditingFields.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.capstone.maru.domain;

import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.ToString;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.format.annotation.DateTimeFormat;

@Getter
@ToString(callSuper = true)
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class AuditingFields {

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@CreatedDate
@Column(nullable = false)
protected LocalDateTime createdAt; // 생성일시

@CreatedBy
@Column(nullable = false, updatable = false, length = 100)
protected String createdBy; // 생성자

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@LastModifiedDate
@Column(nullable = false)
protected LocalDateTime modifiedAt; // 수정일시

@LastModifiedBy
@Column(nullable = false, length = 100)
protected String modifiedBy; // 수정자
}
94 changes: 94 additions & 0 deletions src/main/java/org/capstone/maru/domain/MemberAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package org.capstone.maru.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import java.util.Objects;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.capstone.maru.dto.Role;
import org.capstone.maru.dto.SocialType;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(callSuper = true)
@Table(indexes = {
@Index(columnList = "memberId", unique = true),
@Index(columnList = "email", unique = true),
@Index(columnList = "createdAt"),
@Index(columnList = "createdBy")
})
@Entity
public class MemberAccount extends AuditingFields {

@Id
@Column(nullable = false, length = 50)
private String memberId;

@Setter
@Column(length = 100)
private String email;

@Setter
@Column(length = 100)
private String nickname;

private SocialType socialType;

private Role role;

@Builder
private MemberAccount(
String memberId,
String email,
String nickname,
String createdBy,
SocialType socialType
) {
this.memberId = memberId;
this.email = email;
this.nickname = nickname;
this.createdBy = createdBy;
this.modifiedBy = createdBy;
this.socialType = socialType;
}

public static MemberAccount of(
String memberId,
String email,
String nickname
) {
return new MemberAccount(memberId, email, nickname, null, null);
}

public static MemberAccount of(
String memberId,
String email,
String nickname,
String createdBy
) {
return new MemberAccount(memberId, email, nickname, createdBy, null);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof MemberAccount that)) {
return false;
}
return this.getMemberId() != null && this.getMemberId().equals(that.getMemberId());
}

@Override
public int hashCode() {
return Objects.hash(this.getMemberId());
}
}
14 changes: 14 additions & 0 deletions src/main/java/org/capstone/maru/dto/CustomOAuth2User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.capstone.maru.dto;

import java.util.Collection;
import java.util.Map;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;

public class CustomOAuth2User extends DefaultOAuth2User {

public CustomOAuth2User(Collection<? extends GrantedAuthority> authorities,
Map<String, Object> attributes, String nameAttributeKey, String email) {
super(authorities, attributes, nameAttributeKey);
}
}
21 changes: 21 additions & 0 deletions src/main/java/org/capstone/maru/dto/KakaoOAuth2UserInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.capstone.maru.dto;

import java.util.Map;

public class KakaoOAuth2UserInfo extends OAuth2UserInfo {

public KakaoOAuth2UserInfo(Map<String, Object> attributes) {
super(attributes);
}

@Override
public String getId() {
return String.valueOf(attributes.get("id"));
}

@Override
public String getNickname() {
return null;
}

}
Loading

0 comments on commit f2beff6

Please sign in to comment.