Skip to content

Commit 41f0b39

Browse files
committed
feat kookmin-sw#2 - 카카오로 응답 받은 사용자 정보 데이터, 게시판 권한 틀 구성
카카오로부터 응답 받은 파라미터를 KakaoOAuth2Repsonse 객체에 저장 스프링 시큐리티와 OAuth2.0에서 필요한 Principal 작성 추후에 커스터마이즈 필요
1 parent dd15772 commit 41f0b39

File tree

4 files changed

+201
-0
lines changed

4 files changed

+201
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
package org.capstone.maru.config;public class SecurityConfig {
2+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
package org.capstone.maru.controller;public class MainController {
2+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.capstone.maru.dto.security;
2+
3+
import java.time.LocalDateTime;
4+
import java.time.ZoneId;
5+
import java.time.format.DateTimeFormatter;
6+
import java.util.Map;
7+
8+
/**
9+
* https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#req-user-info 카카오로부터 사용자 정보를 불러올
10+
* 때 카카오에서 응답 메시지 형식을 맞춘 것이다. 자세한 내용은 위 링크를 참조
11+
*/
12+
@SuppressWarnings("unchecked")
13+
public record KakaoOAuth2Response(
14+
Long id,
15+
LocalDateTime connectedAt,
16+
Map<String, Object> properties,
17+
KakaoAccount kakaoAccount
18+
) {
19+
20+
public record KakaoAccount(
21+
Boolean profileNicknameNeedsAgreement,
22+
Profile profile,
23+
Boolean hasEmail,
24+
Boolean emailNeedsAgreement,
25+
Boolean isEmailValid,
26+
Boolean isEmailVerified,
27+
String email
28+
) {
29+
30+
public record Profile(String nickname) {
31+
32+
public static Profile from(Map<String, Object> attributes) {
33+
return new Profile(String.valueOf(attributes.get("nickname")));
34+
}
35+
}
36+
37+
public static KakaoAccount from(Map<String, Object> attributes) {
38+
return new KakaoAccount(
39+
Boolean.valueOf(String.valueOf(attributes.get("profile_nickname_needs_agreement"))),
40+
Profile.from((Map<String, Object>) attributes.get("profile")),
41+
Boolean.valueOf(String.valueOf(attributes.get("has_email"))),
42+
Boolean.valueOf(String.valueOf(attributes.get("email_needs_agreement"))),
43+
Boolean.valueOf(String.valueOf(attributes.get("is_email_valid"))),
44+
Boolean.valueOf(String.valueOf(attributes.get("is_email_verified"))),
45+
String.valueOf(attributes.get("email"))
46+
);
47+
}
48+
49+
public String nickname() {
50+
return this.profile().nickname();
51+
}
52+
}
53+
54+
public static KakaoOAuth2Response from(Map<String, Object> attributes) {
55+
return new KakaoOAuth2Response(
56+
Long.valueOf(String.valueOf(attributes.get("id"))),
57+
LocalDateTime.parse(
58+
String.valueOf(attributes.get("connected_at")),
59+
DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.systemDefault())
60+
),
61+
(Map<String, Object>) attributes.get("properties"),
62+
KakaoAccount.from((Map<String, Object>) attributes.get("kakao_account"))
63+
);
64+
}
65+
66+
public String email() {
67+
return this.kakaoAccount().email();
68+
}
69+
70+
public String nickname() {
71+
return this.kakaoAccount().nickname();
72+
}
73+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package org.capstone.maru.dto.security;
2+
3+
import java.util.Collection;
4+
import java.util.Map;
5+
import java.util.Set;
6+
import java.util.stream.Collectors;
7+
import lombok.Getter;
8+
import org.capstone.maru.dto.MemberAccountDto;
9+
import org.springframework.security.core.GrantedAuthority;
10+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
11+
import org.springframework.security.core.userdetails.UserDetails;
12+
import org.springframework.security.oauth2.core.user.OAuth2User;
13+
14+
public record SharedPostPrincipal(
15+
String memberId,
16+
String email,
17+
String nickname,
18+
Collection<? extends GrantedAuthority> authorities,
19+
Map<String, Object> oAuth2Attributes
20+
) implements UserDetails, OAuth2User {
21+
22+
public static SharedPostPrincipal of(
23+
String memberId,
24+
String email,
25+
String nickname
26+
) {
27+
return of(memberId, email, nickname, Map.of());
28+
}
29+
30+
public static SharedPostPrincipal of(
31+
String memberId,
32+
String email,
33+
String nickname,
34+
Map<String, Object> oAuth2Attributes
35+
) {
36+
Set<RoleType> roleTypes = Set.of(RoleType.MEMBER);
37+
38+
return new SharedPostPrincipal(
39+
memberId,
40+
email,
41+
nickname,
42+
roleTypes
43+
.stream()
44+
.map(RoleType::getName)
45+
.map(SimpleGrantedAuthority::new)
46+
.collect(Collectors.toUnmodifiableSet()),
47+
oAuth2Attributes
48+
);
49+
}
50+
51+
public static SharedPostPrincipal from(MemberAccountDto dto) {
52+
return SharedPostPrincipal.of(
53+
dto.memberId(),
54+
dto.email(),
55+
dto.nickname()
56+
);
57+
}
58+
59+
public MemberAccountDto toDto() {
60+
return MemberAccountDto.of(
61+
memberId,
62+
email,
63+
nickname
64+
);
65+
}
66+
67+
// -- OAuth2User -- //
68+
@Override
69+
public String getName() {
70+
return memberId;
71+
}
72+
73+
@Override
74+
public Map<String, Object> getAttributes() {
75+
return oAuth2Attributes;
76+
}
77+
78+
// -- UserDetails -- //
79+
@Override
80+
public String getUsername() {
81+
return memberId;
82+
}
83+
84+
@Override
85+
public String getPassword() {
86+
return null;
87+
}
88+
89+
@Override
90+
public Collection<? extends GrantedAuthority> getAuthorities() {
91+
return authorities;
92+
}
93+
94+
@Override
95+
public boolean isAccountNonExpired() {
96+
return true;
97+
}
98+
99+
@Override
100+
public boolean isAccountNonLocked() {
101+
return true;
102+
}
103+
104+
@Override
105+
public boolean isCredentialsNonExpired() {
106+
return true;
107+
}
108+
109+
@Override
110+
public boolean isEnabled() {
111+
return true;
112+
}
113+
114+
public enum RoleType {
115+
MEMBER("ROLE_MEMBER");
116+
117+
@Getter
118+
private final String name;
119+
120+
RoleType(String name) {
121+
this.name = name;
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)