This commit is contained in:
@@ -46,10 +46,9 @@ func (f *Middlewares) AuthFrontend(ctx fiber.Ctx) error {
|
|||||||
u.Path = "/v1/auth/phone"
|
u.Path = "/v1/auth/phone"
|
||||||
fullUrl = u.String()
|
fullUrl = u.String()
|
||||||
|
|
||||||
// check cookie exists
|
// 仅使用 Header 的 Bearer Token(前端 localStorage 存储,随请求透传)。
|
||||||
cookie := ctx.Cookies("token")
|
token := ctx.Get("Authorization")
|
||||||
log.Infof("cookie: %s", cookie)
|
if token == "" {
|
||||||
if cookie == "" {
|
|
||||||
log.Infof("auth redirect_uri: %s", fullUrl)
|
log.Infof("auth redirect_uri: %s", fullUrl)
|
||||||
if ctx.XHR() {
|
if ctx.XHR() {
|
||||||
return ctx.SendStatus(fiber.StatusUnauthorized)
|
return ctx.SendStatus(fiber.StatusUnauthorized)
|
||||||
@@ -57,10 +56,8 @@ func (f *Middlewares) AuthFrontend(ctx fiber.Ctx) error {
|
|||||||
return ctx.Redirect().To(fullUrl)
|
return ctx.Redirect().To(fullUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
jwt, err := f.jwt.Parse(cookie)
|
jwt, err := f.jwt.Parse(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// remove cookie
|
|
||||||
ctx.ClearCookie("token")
|
|
||||||
if ctx.XHR() {
|
if ctx.XHR() {
|
||||||
return ctx.SendStatus(fiber.StatusUnauthorized)
|
return ctx.SendStatus(fiber.StatusUnauthorized)
|
||||||
}
|
}
|
||||||
@@ -69,8 +66,6 @@ func (f *Middlewares) AuthFrontend(ctx fiber.Ctx) error {
|
|||||||
|
|
||||||
user, err := services.Users.FindByID(ctx.Context(), jwt.UserID)
|
user, err := services.Users.FindByID(ctx.Context(), jwt.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// remove cookie
|
|
||||||
ctx.ClearCookie("token")
|
|
||||||
if ctx.XHR() {
|
if ctx.XHR() {
|
||||||
return ctx.SendStatus(fiber.StatusUnauthorized)
|
return ctx.SendStatus(fiber.StatusUnauthorized)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function getCurrentPathWithQueryHash() {
|
|||||||
const client = axios.create({
|
const client = axios.create({
|
||||||
baseURL: '/v1',
|
baseURL: '/v1',
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
withCredentials: true,
|
withCredentials: false,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-Requested-With': 'XMLHttpRequest',
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
@@ -21,6 +21,11 @@ const client = axios.create({
|
|||||||
// Request interceptor
|
// Request interceptor
|
||||||
client.interceptors.request.use(
|
client.interceptors.request.use(
|
||||||
config => {
|
config => {
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
if (token) {
|
||||||
|
config.headers = config.headers || {};
|
||||||
|
config.headers['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
|
||||||
|
}
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
@@ -45,6 +50,7 @@ client.interceptors.response.use(
|
|||||||
const redirectPath = encodeURIComponent(getCurrentPathWithQueryHash());
|
const redirectPath = encodeURIComponent(getCurrentPathWithQueryHash());
|
||||||
sessionStorage.setItem('post_auth_redirect', getCurrentPathWithQueryHash());
|
sessionStorage.setItem('post_auth_redirect', getCurrentPathWithQueryHash());
|
||||||
sessionStorage.removeItem('phone_verified');
|
sessionStorage.removeItem('phone_verified');
|
||||||
|
localStorage.removeItem('token');
|
||||||
window.location.href = `/verify-phone?redirect=${redirectPath}`;
|
window.location.href = `/verify-phone?redirect=${redirectPath}`;
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useRouter } from 'vue-router'
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const activeTab = ref(0)
|
const activeTab = ref(0)
|
||||||
const isPhoneVerified = () => sessionStorage.getItem('phone_verified') === '1'
|
const isAuthed = () => Boolean(localStorage.getItem('token'))
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ label: '列表', route: '/', icon: AiOutlineHome },
|
{ label: '列表', route: '/', icon: AiOutlineHome },
|
||||||
@@ -14,7 +14,7 @@ const tabs = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const switchTab = (index, route) => {
|
const switchTab = (index, route) => {
|
||||||
if ((route === '/purchased' || route === '/profile') && !isPhoneVerified()) {
|
if ((route === '/purchased' || route === '/profile') && !isAuthed()) {
|
||||||
const redirect = encodeURIComponent(route)
|
const redirect = encodeURIComponent(route)
|
||||||
router.replace(`/verify-phone?redirect=${redirect}`)
|
router.replace(`/verify-phone?redirect=${redirect}`)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ const updateMediaSource = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleBuy = async () => {
|
const handleBuy = async () => {
|
||||||
if (sessionStorage.getItem('phone_verified') !== '1') {
|
if (!localStorage.getItem('token')) {
|
||||||
const redirect = encodeURIComponent(router.currentRoute.value.fullPath);
|
const redirect = encodeURIComponent(router.currentRoute.value.fullPath);
|
||||||
router.replace(`/verify-phone?redirect=${redirect}`);
|
router.replace(`/verify-phone?redirect=${redirect}`);
|
||||||
return;
|
return;
|
||||||
@@ -142,7 +142,7 @@ const handleBuy = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to initiate payment:", error);
|
console.error("Failed to initiate payment:", error);
|
||||||
// alert("发起支付失败,请稍后重试");
|
// alert("发起支付失败,请稍后重试");
|
||||||
alert(error.response?.data || "发起支付失败,请稍后重试");
|
alert(error.response?.data?.message || "发起支付失败,请稍后重试");
|
||||||
} finally {
|
} finally {
|
||||||
buying.value = false;
|
buying.value = false;
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,8 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<div v-if="article && !article.bought" class="bg-white border-b border-gray-200">
|
<div v-if="article && !article.bought" class="bg-white border-b border-gray-200">
|
||||||
<div v-if="article.recharge_wechat" class="text-sm bg-orange-500 text-white px-4 py-2">
|
<div v-if="article.recharge_wechat" class="text-sm bg-orange-500 text-white px-4 py-2">
|
||||||
注意:未购买视频仅可预览 1 分钟,购买后可观看全集。账户充值购买联系微信:<span class="font-bold">{{ article.recharge_wechat }}</span>
|
注意:未购买视频仅可预览 1 分钟,购买后可观看全集。账户充值购买联系微信:<span class="font-bold">{{ article.recharge_wechat
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-between max-w-md mx-auto p-4">
|
<div class="flex items-center justify-between max-w-md mx-auto p-4">
|
||||||
<div class="text-orange-600 text-2xl">
|
<div class="text-orange-600 text-2xl">
|
||||||
|
|||||||
@@ -58,7 +58,13 @@ const handleVerify = async () => {
|
|||||||
if (!canVerify.value) return;
|
if (!canVerify.value) return;
|
||||||
verifying.value = true;
|
verifying.value = true;
|
||||||
try {
|
try {
|
||||||
await authApi.validateSmsCode(phone.value, code.value);
|
const resp = await authApi.validateSmsCode(phone.value, code.value);
|
||||||
|
const token = resp?.data?.token || resp?.data?.Token;
|
||||||
|
if (!token) {
|
||||||
|
alert("验证失败:未返回 token");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
localStorage.setItem("token", String(token));
|
||||||
sessionStorage.setItem("phone_verified", "1");
|
sessionStorage.setItem("phone_verified", "1");
|
||||||
const redirect =
|
const redirect =
|
||||||
normalizeRedirect(route.query.redirect) ||
|
normalizeRedirect(route.query.redirect) ||
|
||||||
@@ -67,7 +73,7 @@ const handleVerify = async () => {
|
|||||||
sessionStorage.removeItem("post_auth_redirect");
|
sessionStorage.removeItem("post_auth_redirect");
|
||||||
router.replace(redirect);
|
router.replace(redirect);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error?.response?.data || "验证失败");
|
alert(error?.response?.data?.message || "验证失败");
|
||||||
} finally {
|
} finally {
|
||||||
verifying.value = false;
|
verifying.value = false;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user