์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- ํ๋ก ํธ์ค๋
- ๋ฐฑ์ค
- ๊ทธ๋ฆฌ๋์๊ณ ๋ฆฌ์ฆ
- ๋จ์ํ ์คํธ
- ์ฐ์ ์์ํ
- ์น๊ฐ๋ฐ๊ธฐ๋ก
- ๋ฆฌ์กํธ
- ๋ฐฑ์คํ์ด
- SSE
- ChatGPT
- spring
- ์ปด๊ณต์
- ์คํ๋ง
- boj11653
- ํ๋ก๊ทธ๋๋ฐ
- ๋ฐฑ์๋
- ์๊ณ ๋ฆฌ์ฆ
- ์ฝ๋ฉ
- ํ์ด์ฌ
- ๋ฐฑ์ค1436
- ์ดํญ๊ณ์
- ๊ฐ๋ฐ์
- ์ปด๊ณต
- ๋ฆฌ์กํธ๋ค์ดํฐ๋ธ
- ๊ทธ๋ฆฌ๋
- ์๋ฃ๊ตฌ์กฐ
- ์ฝ๋ฉํ ์คํธ
- ์ปดํจํฐ๊ณตํ
- ์น๊ฐ๋ฐ
- ๋ชจ๋ฐ์ผ์ฑํ๋ก๊ทธ๋๋ฐ
- Today
- Total
๐ป๐ญ๐ง๐
[์น ๊ฐ๋ฐ ํ๋ก์ ํธ] 9. ์คํ๋ง Spring ๊ตฌ๊ธ ์์ ๋ก๊ทธ์ธ ๋ก์ง ๋ณ๊ฒฝ (๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ ์น๋ทฐ ๊ด๋ จ) ๋ณธ๋ฌธ
[์น ๊ฐ๋ฐ ํ๋ก์ ํธ] 9. ์คํ๋ง Spring ๊ตฌ๊ธ ์์ ๋ก๊ทธ์ธ ๋ก์ง ๋ณ๊ฒฝ (๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ ์น๋ทฐ ๊ด๋ จ)
adorableco 2024. 2. 2. 00:19์ด๋ฒ ํ๋ก์ ํธ ์ค์ ์ ค ๋งํ๋ ๋ฌธ์ ...
๋ฌธ์ ๊ฐ ์ด๋์ ๋ฐ์ํ๋.. ํ๋ฉด์
์๋ ๊ตฌ๊ธ ์์ ๋ก๊ทธ์ธ์ A to Z๋ฅผ ๋ฐฑ์๋์์ ๋ด๋นํ๋๋ก ๊ตฌํ์ ํ๋ค.
์ค๋๋ง์ ์ํ์ค ๋ค์ด์ด๊ทธ๋จ๋ ๊ทธ๋ ค๋ดค๋๋ฐ ์๋์ ๊ฐ๋ค.
(draw. io ๋ ๊ทธ๋ฆฌ๊ธฐ๋ ์ฐธ ํธ๋ฆฌํ๋ฐ ์ ์ฅํ ๋ ํ์ง์ด ์กฐ๊ธ๋ง ๋ ๊ฐ์ ๋๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.. .ใ
..)
๋ก๊ทธ์ธ ์์ฒญ๋ถํฐ Authorization Code๋ฅผ ๋ฐ์ ์ฌ์ฉ์ ์ ๋ณด ์์ฒญํ๋ ๊ฒ๊น์ง ์๋ฒ์์ ์งํ์ ํ๊ณ
์ต์ข
accessToken ๋๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ํด๋ผ์ด์ธํธ ์ธก์ผ๋ก ๋ฐํํ๋๋ก ๊ตฌํํ์๋ค.
(ํ์์ด๋ฉด ์ธ์ฆ/์ธ๊ฐ๋ฅผ ์ํ accessToken๋ง, ๋นํ์์ด๋ผ๋ฉด ํ์๊ฐ์
์ ๋ฐ๋ก ์งํํ ์ ์๋๋ก
์ฌ์ฉ์์ ๋ณด (name
, email
, picture
) ์ ๋ด์๋ณด๋ธ๋ค.
๊ทผ๋ฐ ์ ๋ง ์์์น๋ ๋ชปํ๊ฒ ํ๋ก ํธ(React Native Expo) ์์ ์ฐ๊ฒฐ์์ ์ค๋ฅ๊ฐ ๋ฌ๋ค..
์น์ด๋ ์ฑ์ด๋ ๋ฌด์์ ๊ฐ์ง ์๊ฒ ์ง.. ๋ผ๊ณ ์๊ฐํ๊ธด ํ์ง๋ง...
์ฒ์ ์๋๋ WebView
๋ฅผ ํตํด ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์ฐฝ์ผ๋ก ์ด๋ํ๋ ๊ฒ์ด์๋ค. ์ผ๋จ ์ฌ๊ธฐ์๋ ๋งค๋๋ฝ์ง๋ง์ ์์๋๊ฒ, ๊ตฌ๊ธ์ด ์น๋ทฐ ์ด์ฉ์ ๋ง์์ ์น๋ทฐ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์๋์ ๊ฐ์ด userAgent
์ ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๋ฅผ ์
๋ ฅํ์ฌ ์ฐํํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ผ ํ๋ค.
<WebView
source={{ uri: url }}
onNavigationStateChange={handleNavigationStateChange}
userAgent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
style={{ flex: 1 }}
/>
๊ทธ๋ฆฌ๊ณ ๋ฉ์ธ ๋ฌธ์ ๋ ๋ก๊ทธ์ธ ์๋ฃ ํ์ ๊ฐ์ ธ์์ผํ json ์ ๋ณด๋ค์ ์ด ์น๋ทฐ ๋ธ๋ผ์ฐ์ ์์ ์ฑ์ผ๋ก ๋ณด๋ผ ๋ฐฉ๋ฒ์ ๋์ ํ ๋ชป์ฐพ๊ฒ ๋ค๋ ๊ฒ์ด์๋ค. (์๋ง ์ ์ด์ ๋ฐฉ๋ฒ์ด ์๋ ๊ฒ ๊ฐ๋ค... ์์ผ๋ฉด ์๋ ค์ฃผ์๊ธธ ๋ฐ๋๋๋ค..)
๋ก๊ทธ์ธ์ ํ๊ณ
์ฌ์ฉ์ ์ ๋ณด json ์ด ๋ฐํ๋ ์ํ์ด๋ค.
ํ์ฌ ์ฑ์ด ์๋๋ผ ์ธ๋ถ ๋ธ๋ผ์ฐ์ ์ ์๋ ์ํ์ด๋ ๊ฐ์ ธ์ฌ ์๊ฐ ์๋ ๊ฒ์ด๋ค.๋ฌด์์ ์ฌ๊ธฐ์ ์ด๋ป๊ฒ ๊ฐ์ ธ์ฌ๊น๋ง ํ๋ฃจ์ข ์ผ ๊ณ ๋ฏผํ๋ค๊ฐ
๋ค๋ฅธ ๋๊ธฐ์๊ฒ ์๊ฒฌ์ ๊ตฌํด๋ณธ ๊ฒฐ๊ณผ ๊ตฌ๊ธ ๋ก๊ทธ์ธ ์์ฒญ์ ํ๋ก ํธ์์ ๊ตฌ๊ธ๋ก ์ง์ ๋ณด๋ด๋ ๊ฒ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ๋ก ํ๋ค!
๋ณดํต์ ์ด๋ฐ ๋ก์ง์ผ๋ก ํ๋ค๋ค์)
๊ทธ๋์ ์ต์ข ์ ์ผ๋ก ๋ณ๊ฒฝํ ๊ฒ์ ์๋์ ๊ฐ๋ค
ํ์คํ ๋ญ๊ฐ ๋ ๋ถ์ ํ๊ฐ ๋์๋ค
๋ฐฑ์๋ ์ฝ๋๋ ํฌ๊ฒ ๋ฌ๋ผ์ง๊ฑด ์์ด์ ํ๋ก ํธ ์ชฝ ์ฝ๋๋ง ํ๋ฒ์ฉ ์ธ๊ธ์ ํ๊ฒ ๋ค
/** @format */
import * as React from "react";
import * as WebBrowser from "expo-web-browser";
import * as Google from "expo-auth-session/providers/google";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { Button, View, Text, StyleSheet, TouchableOpacity } from "react-native";
import { useEffect } from "react";
import axios from "axios";
WebBrowser.maybeCompleteAuthSession();
export default function GoogleLogin() {
const [request, response, promptAsync] = Google.useAuthRequest({
webClientId: process.env.EXPO_PUBLIC_WEB_CLIENT_ID,
androidClientId: EXPO_PUBLIC_ANDROID_CLIENT_ID,
});
const [userInfo, setUserInfo] = React.useState(null);
const handleSignInWithGoogle = async () => {
const user = await AsyncStorage.getItem("@accessToken");
if (!user) {
if (response?.type === "success") {
await sendToken(response.authentication?.accessToken);
}
}
};
//๊ตฌ๊ธ๋ก๊ทธ์ธ์ ํด์ ๋ฐ์ ํ ํฐ์ ๋ฐฑ์๋๋ก ๋ณด๋ด์ ๋๋น์ ์๋ ํ์ ๋ด์ฉ ์กฐํ ์์
const sendToken = async (token) => {
await axios
.get(`http://fit-friends.duckdns.org:8081/api/login/${token}`)
.then(async (res) => {
if (res.data.accessToken == null) {
setUserInfo(res.data);
// ํ์๊ฐ์
ํด์ผ ํจ
} else {
console.log("accessToken = ", res.data.accessToken);
await AsyncStorage.setItem(
"@accessToken",
JSON.stringify(res.data.accessToken),
);
}
});
};
const handleLogout = async () => {
await AsyncStorage.removeItem("@user");
setUserInfo(null);
};
useEffect(() => {
handleSignInWithGoogle();
}, [response]);
return (
<View>
<TouchableOpacity
style={[styles.buttonStyle, { marginBottom: 18 }]}
disabled={!request}
title='Login'
onPress={() => {
promptAsync();
}}
>
<Text style={styles.buttonTextStyle}>๋ก๊ทธ์ธํ์ฌ ์์ํ๊ธฐ</Text>
</TouchableOpacity>
<Button title='logout' onPress={() => handleLogout()} />
</View>
);
}
๊ตฌ๊ธ ๋ก๊ทธ์ธ์ ์ง์ํ๋ expo ์ ์ฌ๋ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ๊ตฌํํ์๋ค.
๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ฅด๋ฉด
const handleSignInWithGoogle = async () => {
const user = await AsyncStorage.getItem("@accessToken");
if (!user) {
if (response?.type === "success") {
await sendToken(response.authentication?.accessToken);
}
}
};
์ด ๋ฉ์๋์์ ๋จผ์ AsyncStorage ์ ์ ์ฅ๋ผ์๋ accessToken
๊ฐ์ ๊ฐ์ ธ์ ๋ก๊ทธ์ธ ์ํ์ธ์ง ํ์ธํ๊ณ ๊ฐ์ด ์๋ค๋ฉด
๋ฐฑ์๋์์ ๊ตฌ๊ธ์๊ฒ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์์ฒญํ ์ ์๋๋ก ๊ตฌ๊ธ๋ก๋ถํฐ ๋ฐ์ ์ฝ๋(๋ณ์ accessToken
) ๋ฅผ ์ ๋ฌํ๋ค.
๊ทธ๊ฒ์ด ์๋์ sendToken
๋ฉ์๋์ด๋ค.
๋ค์๋ณด๋ ํท๊ฐ๋ฆฌ๊ฒ ์ ์ด๋๋๋ฐ AsyncStorage์ ์ ์ฅํด๋๋
accessToken
์ ์คํ๋ง ์๋ฒ์์ ์ ๊ณตํ๋ ์ฌ์ฉ์ ์ธ๊ฐ์ฉjwt ํ ํฐ์ด๊ณ ๋ฐฑ์๋์ ๋ณด๋ด๋accessToken
์ ๊ตฌ๊ธ์ฉ ์ธ๊ฐ์ฝ๋์ด๋ค!
sendToken()
await axios
.get(`{๋ฐฑ์๋ api ์ฃผ์}/api/login/${token}`)
.then(async (res) => {
if (res.data.accessToken == null) {
setUserInfo(res.data);
// ํ์๊ฐ์
ํด์ผ ํจ
} else {
console.log("accessToken = ", res.data.accessToken);
await AsyncStorage.setItem(
"@accessToken",
JSON.stringify(res.data.accessToken),
);
}
});
};
AsyncStorage
๋@react-native-async-storage/async-storage
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋๊ฑด๋ฐ
์ฑ์์ ์๋ ์์ ์น ๋ธ๋ผ์ฐ์ ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง ์ญํ ์ ํ๋ ๊ฒ ๊ฐ๋ค.
์ค์ ๋ก ์ง๊ธ expo ์ฑ์ด ์๋๋ก์ด๋์์ ์ค๋ฅ๊ฐ ๊ณ์ ๋์ ์น์ผ๋ก ๊ฐ๋ฐ์ ํ๊ณ ์๋๋ฐ
ํ์ธํด๋ณด๋ฉด ๋ก์ปฌ์คํ ๋ฆฌ์ง์accessToken
๊ฐ์ด ์ ์ฅ๋๋ค.
๋๋์ด ๋ด๊ฐ ์๊ฐํ๋๋๋ก ์๋์ ํ๋ค..... ์์ง ํด๊ฒฐํ ๋ฌธ์ ๋ค์ ์๊ธด ํ์ง๋ง (expo ์ฑ์ด ์๋๋ก์ด๋ ๋น๋๊ฐ ์๋จ, expo๋ .env ์ ๋ณ์ ์ด๋ฆ์ EXPO_PUBLIC_{NAME}
์ผ๋ก ํ๋ฉด ๋๋ค๋๋ฐ ๋ณ์๊ฐ์ด ๋ถ๋ฌ์์ง์ง ์์..)
๊ทธ๋๋ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ ๋คํ์ด๋ค....
ํ ์ํ ์.........