Feat: AuthRouter & CleanNeteaseCache API
前端增加限制访问的路由,后端调整鉴权接口,增加清除网易云缓存接口
This commit is contained in:
parent
3bb999aed5
commit
2f09fcabe4
|
|
@ -7,6 +7,15 @@ datasource db {
|
||||||
url = env("DB_URL")
|
url = env("DB_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model User {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
name String @unique
|
||||||
|
email String @unique
|
||||||
|
password String
|
||||||
|
created_at DateTime @default(now())
|
||||||
|
updated_at DateTime?
|
||||||
|
}
|
||||||
|
|
||||||
model ACGM {
|
model ACGM {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
title String?
|
title String?
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,13 @@ const songs: Prisma.ACGMCreateInput[] = [
|
||||||
bangumi: "这个美术部有问题",
|
bangumi: "这个美术部有问题",
|
||||||
music_id: 435288259
|
music_id: 435288259
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "みずきのテーマ",
|
||||||
|
artist: "吟",
|
||||||
|
album: "この美術部には問題がある! オリジナルサウンドトラックCD vol.1",
|
||||||
|
bangumi: "这个美术部有问题",
|
||||||
|
music_id: 435288260
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "伝える勇気があったなら",
|
title: "伝える勇気があったなら",
|
||||||
artist: "吟",
|
artist: "吟",
|
||||||
|
|
@ -85,6 +92,14 @@ async function main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
name: "Paul",
|
||||||
|
email: "dreamer_paul@126.com",
|
||||||
|
password: "123456",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
console.log(`Seeding finished.`);
|
console.log(`Seeding finished.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// React
|
||||||
|
import React from "react";
|
||||||
|
import { useRequest } from "ahooks";
|
||||||
|
import useStat from "@/hooks/useStat";
|
||||||
|
|
||||||
|
|
||||||
|
// UI
|
||||||
|
import Button from "@/components/Base/Button";
|
||||||
|
|
||||||
|
|
||||||
|
// Tool
|
||||||
|
import addMusicRequest from "@/server/api/admin/acgm/add";
|
||||||
|
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
import { MouseEvent, ChangeEvent } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
function AddACGM() {
|
||||||
|
const { loading, run } = useRequest(
|
||||||
|
(params) => addMusicRequest({
|
||||||
|
query: params
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
manual: true,
|
||||||
|
onSuccess: (data) => {
|
||||||
|
console.log(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const [input, setInput] = useStat({
|
||||||
|
id: "",
|
||||||
|
bangumi: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (ev: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
run(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onInputChange = (ev: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setInput({ [ev.target.name]: ev.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<fieldset>
|
||||||
|
<label>
|
||||||
|
<span>添加一个随机动漫音乐</span>
|
||||||
|
<div className="input-group">
|
||||||
|
<input type="text" name="id" placeholder="输入网易云 ID"
|
||||||
|
value={input.id} onChange={onInputChange}
|
||||||
|
/>
|
||||||
|
<input type="text" name="bangumi" placeholder="输入番剧名称"
|
||||||
|
value={input.bangumi} onChange={onInputChange}
|
||||||
|
/>
|
||||||
|
<Button onClick={onSubmit} loading={loading}>添加</Button>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddACGM;
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
// React
|
||||||
|
import React from "react";
|
||||||
|
import { useRequest } from "ahooks";
|
||||||
|
import useStat from "@/hooks/useStat";
|
||||||
|
|
||||||
|
|
||||||
|
// UI
|
||||||
|
import Button from "@/components/Base/Button";
|
||||||
|
|
||||||
|
|
||||||
|
// Tool
|
||||||
|
import cleanCacheRequest from "@/server/api/admin/netease/clean";
|
||||||
|
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
import { MouseEvent, ChangeEvent } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
function RemoveMusicCache() {
|
||||||
|
const { loading, run } = useRequest(
|
||||||
|
(params) => cleanCacheRequest({
|
||||||
|
query: params
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
manual: true,
|
||||||
|
onSuccess: (data) => {
|
||||||
|
console.log(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const [input, setInput] = useStat({
|
||||||
|
id: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (ev: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
run(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onInputChange = (ev: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setInput({ [ev.target.name]: ev.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<fieldset>
|
||||||
|
<label>
|
||||||
|
<span>清除一个网易云音乐缓存</span>
|
||||||
|
<div className="input-group">
|
||||||
|
<input type="text" name="id" placeholder="输入网易云 ID"
|
||||||
|
value={input.id} onChange={onInputChange}
|
||||||
|
/>
|
||||||
|
<Button onClick={onSubmit} loading={loading}>清除</Button>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RemoveMusicCache;
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// React
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
interface ButtonProps {
|
||||||
|
loading?: boolean
|
||||||
|
children: React.ReactNode
|
||||||
|
|
||||||
|
onClick?: React.MouseEventHandler<HTMLElement>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Component
|
||||||
|
function Button({ loading = false, children, onClick }: ButtonProps) {
|
||||||
|
return (
|
||||||
|
<button className="btn green" onClick={onClick}>
|
||||||
|
{loading ? <i className="fa fa-spinner fa-spin"></i> : children}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Button;
|
||||||
|
|
@ -47,6 +47,7 @@ function Aside() {
|
||||||
<Link to="/acgm">随机动漫音乐</Link>
|
<Link to="/acgm">随机动漫音乐</Link>
|
||||||
<Link to="/bili">哔哩哔哩小窗</Link>
|
<Link to="/bili">哔哩哔哩小窗</Link>
|
||||||
<Link to="/bing">必应每日壁纸</Link>
|
<Link to="/bing">必应每日壁纸</Link>
|
||||||
|
{profile.name && <Link to="/admin">轻管理</Link>}
|
||||||
</nav>
|
</nav>
|
||||||
</nav>
|
</nav>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
// React
|
// React
|
||||||
import React, { useEffect, useLayoutEffect } from "react";
|
import React, { useEffect, useLayoutEffect } from "react";
|
||||||
import useGlobalData from "@/hooks/useGlobalData";
|
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import GlobalContext from "@/components/GlobalContext";
|
|
||||||
import Aside from "@/components/Layout/Aside";
|
import Aside from "@/components/Layout/Aside";
|
||||||
import Footer from "@/components/Layout/Footer";
|
import Footer from "@/components/Layout/Footer";
|
||||||
|
|
||||||
|
|
@ -20,7 +18,6 @@ interface FrontWrapperProps {
|
||||||
// Components
|
// Components
|
||||||
function FrontWrapper(props: FrontWrapperProps) {
|
function FrontWrapper(props: FrontWrapperProps) {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
let [globalData, setGlobalData] = useGlobalData();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const name = import.meta.env.PAUL_SITENAME;
|
const name = import.meta.env.PAUL_SITENAME;
|
||||||
|
|
@ -38,11 +35,11 @@ function FrontWrapper(props: FrontWrapperProps) {
|
||||||
}, [location.pathname]);
|
}, [location.pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GlobalContext.Provider value={{ globalData, setGlobalData }}>
|
<>
|
||||||
<Aside />
|
<Aside />
|
||||||
{props.element}
|
{props.element}
|
||||||
<Footer />
|
<Footer />
|
||||||
</GlobalContext.Provider>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// React
|
||||||
|
import React, { useEffect, useLayoutEffect } from "react";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
import { Suspense } from "react";
|
||||||
|
import { Navigate } from "react-router-dom";
|
||||||
|
import Aside from "@/components/Layout/Aside";
|
||||||
|
import Footer from "@/components/Layout/Footer";
|
||||||
|
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
import { ComponentType, LazyExoticComponent } from "react";
|
||||||
|
|
||||||
|
interface FrontWrapperProps {
|
||||||
|
title?: string
|
||||||
|
element: LazyExoticComponent<ComponentType<any>>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
function FrontWrapperAuth(props: FrontWrapperProps) {
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const auth = document.cookie.includes("paul-logined");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const name = import.meta.env.PAUL_SITENAME;
|
||||||
|
|
||||||
|
if (props.title) {
|
||||||
|
document.title = `${props.title} - ${name}`;
|
||||||
|
}
|
||||||
|
else if (name) {
|
||||||
|
document.title = String(name);
|
||||||
|
}
|
||||||
|
}, [location.pathname]);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
window.scrollTo({ top: 0, left: 0 });
|
||||||
|
}, [location.pathname]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
auth ? (
|
||||||
|
<>
|
||||||
|
<Aside />
|
||||||
|
<Suspense fallback={<i className="fa fa-spinner fa-spin"></i>}>
|
||||||
|
<props.element />
|
||||||
|
</Suspense>
|
||||||
|
<Footer />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Navigate
|
||||||
|
to={{
|
||||||
|
search: "?go=" + location.pathname,
|
||||||
|
pathname: "/login"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FrontWrapperAuth;
|
||||||
|
|
@ -52,6 +52,39 @@ blockquote.notice p{
|
||||||
100% { transform: translateX(-100%) }
|
100% { transform: translateX(-100%) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 输入框组 */
|
||||||
|
.input-group{ display: flex }
|
||||||
|
|
||||||
|
.input-group > input:first-child, .input-group > textarea:first-child, .input-group > select:first-child{
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group > input, .input-group > textarea, .input-group > select{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group > input:not(:first-child), .input-group > textarea:not(:first-child), .input-group > select:not(:first-child){
|
||||||
|
border-left: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group > input:not(:last-child), .input-group > textarea:not(:last-child), .input-group > select:not(:last-child){
|
||||||
|
border-right: none;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group > button:last-child{
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
.input-group > button .fa{
|
||||||
|
width: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
/* 按钮组 */
|
/* 按钮组 */
|
||||||
.btn-group{
|
.btn-group{
|
||||||
row-gap: .5em;
|
row-gap: .5em;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
import React from "react";
|
import React, { lazy } from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
|
|
||||||
|
import useGlobalData from "@/hooks/useGlobalData";
|
||||||
|
import GlobalContext from "@/components/GlobalContext";
|
||||||
|
|
||||||
import "./kico.css";
|
import "./kico.css";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Routes
|
// Routes
|
||||||
import Home from "./pages/index";
|
import Home from "./pages/index";
|
||||||
import Login from "./pages/login";
|
import Login from "./pages/login";
|
||||||
|
|
@ -23,45 +25,54 @@ import NoMatch from "./pages/404";
|
||||||
|
|
||||||
// RouteWrapper
|
// RouteWrapper
|
||||||
import FrontWrapper from "./components/Layout/FrontWrapper";
|
import FrontWrapper from "./components/Layout/FrontWrapper";
|
||||||
|
import FrontWrapperAuth from "./components/Layout/FrontWrapperAuth";
|
||||||
|
|
||||||
|
const admin = lazy(() => import("./pages/admin"));
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
function App() {
|
function App() {
|
||||||
|
let [globalData, setGlobalData] = useGlobalData();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router>
|
<GlobalContext.Provider value={{ globalData, setGlobalData }}>
|
||||||
<Routes>
|
<Router>
|
||||||
<Route path="/" element={
|
<Routes>
|
||||||
<FrontWrapper element={<Home />} />}
|
<Route path="/" element={
|
||||||
/>
|
<FrontWrapper element={<Home />} />}
|
||||||
<Route path="/login" element={
|
/>
|
||||||
<FrontWrapper title="登录" element={<Login />} /> }
|
<Route path="/login" element={
|
||||||
/>
|
<FrontWrapper title="登录" element={<Login />} /> }
|
||||||
<Route path="/notice" element={
|
/>
|
||||||
<FrontWrapper title="使用约定" element={<Notice />} /> }
|
<Route path="/admin" element={
|
||||||
/>
|
<FrontWrapperAuth title="轻管理" element={admin} /> }
|
||||||
<Route path="/log" element={
|
/>
|
||||||
<FrontWrapper title="更新记录" element={<Log />} />}
|
<Route path="/notice" element={
|
||||||
/>
|
<FrontWrapper title="使用约定" element={<Notice />} /> }
|
||||||
<Route path="/netease" element={
|
/>
|
||||||
<FrontWrapper title="网易云解析" element={<Netease />} />}
|
<Route path="/log" element={
|
||||||
/>
|
<FrontWrapper title="更新记录" element={<Log />} />}
|
||||||
<Route path="/wallpaper" element={
|
/>
|
||||||
<FrontWrapper title="随机动漫壁纸" element={<Wallpaper />} />}
|
<Route path="/netease" element={
|
||||||
/>
|
<FrontWrapper title="网易云解析" element={<Netease />} />}
|
||||||
<Route path="/acgm" element={
|
/>
|
||||||
<FrontWrapper title="随机动漫音乐" element={<ACGM />} />}
|
<Route path="/wallpaper" element={
|
||||||
/>
|
<FrontWrapper title="随机动漫壁纸" element={<Wallpaper />} />}
|
||||||
<Route path="/bili" element={
|
/>
|
||||||
<FrontWrapper title="哔哩哔哩小窗" element={<Bili />} />}
|
<Route path="/acgm" element={
|
||||||
/>
|
<FrontWrapper title="随机动漫音乐" element={<ACGM />} />}
|
||||||
<Route path="/bing" element={
|
/>
|
||||||
<FrontWrapper title="必应每日壁纸" element={<Bing />} />}
|
<Route path="/bili" element={
|
||||||
/>
|
<FrontWrapper title="哔哩哔哩小窗" element={<Bili />} />}
|
||||||
<Route path="*" element={
|
/>
|
||||||
<FrontWrapper title="404" element={<NoMatch />} />}
|
<Route path="/bing" element={
|
||||||
/>
|
<FrontWrapper title="必应每日壁纸" element={<Bing />} />}
|
||||||
</Routes>
|
/>
|
||||||
</Router>
|
<Route path="*" element={
|
||||||
|
<FrontWrapper title="404" element={<NoMatch />} />}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
|
</Router>
|
||||||
|
</GlobalContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// React
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
|
// UI
|
||||||
|
import Button from "@/components/Base/Button";
|
||||||
|
import ArticleHead from "@/components/Layout/ArticleHead";
|
||||||
|
|
||||||
|
import AddACGM from "@/components/Admin/AddACGM";
|
||||||
|
import RemoveMusicCache from "@/components/Admin/RemoveMusicCache";
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
function Admin() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<ArticleHead title="轻管理" desc="简单的维护功能" />
|
||||||
|
<form>
|
||||||
|
<AddACGM />
|
||||||
|
|
||||||
|
<RemoveMusicCache />
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Admin;
|
||||||
|
|
@ -31,12 +31,17 @@ function Login() {
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|
||||||
setGlobalData({
|
if (data.data) {
|
||||||
type: "profile",
|
setGlobalData({
|
||||||
value: data.profile
|
type: "profile",
|
||||||
});
|
value: data.data.profile
|
||||||
|
});
|
||||||
|
|
||||||
navigate("/")
|
navigate("/");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alert("错误的用户名或密码");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Api, Post, Query, useContext, useInject, Middleware } from "@midwayjs/hooks";
|
||||||
|
import { RedisService } from "@midwayjs/redis";
|
||||||
|
import { JwtPassportMiddleware } from "../../../middleware/jwt.middleware";
|
||||||
|
|
||||||
|
export default Api(
|
||||||
|
Post(),
|
||||||
|
Middleware(JwtPassportMiddleware),
|
||||||
|
Query<{ id: string, bangumi: string }>(),
|
||||||
|
async () => {
|
||||||
|
const ctx = useContext();
|
||||||
|
const client = await useInject(RedisService);
|
||||||
|
|
||||||
|
const { id } = ctx.query;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
msg: "Required id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.del(`api-next:163:${id}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: 1,
|
||||||
|
msg: "Success"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Api, Get, Query, useContext, useInject } from "@midwayjs/hooks";
|
import { Api, Get, Query, useContext, useInject } from "@midwayjs/hooks";
|
||||||
import { JwtService } from '@midwayjs/jwt';
|
import { JwtService } from "@midwayjs/jwt";
|
||||||
|
import { prisma } from "../../utils/prisma";
|
||||||
|
|
||||||
export default Api(
|
export default Api(
|
||||||
Get(),
|
Get(),
|
||||||
|
|
@ -11,17 +12,42 @@ export default Api(
|
||||||
|
|
||||||
const token = await jwt.sign({ name: "Paul" });
|
const token = await jwt.sign({ name: "Paul" });
|
||||||
|
|
||||||
|
const user = await prisma.user.findFirst({
|
||||||
|
where: {
|
||||||
|
name: ctx.query.username,
|
||||||
|
password: ctx.query.password
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return {
|
||||||
|
code: 0,
|
||||||
|
msg: "Invalid username or password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Token
|
||||||
ctx.cookies.set("paul-token", token, {
|
ctx.cookies.set("paul-token", token, {
|
||||||
maxAge: 60 * 60 * 24 * 2,
|
maxAge: 60 * 60 * 24 * 2 * 100,
|
||||||
httpOnly: true
|
httpOnly: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 标记已登录
|
||||||
|
ctx.cookies.set("paul-logined", 1, {
|
||||||
|
maxAge: 60 * 60 * 24 * 2 * 100,
|
||||||
|
httpOnly: false
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
profile: {
|
code: 1,
|
||||||
name: "Paul",
|
msg: "Success",
|
||||||
avatar: "https://sdn.geekzu.org/avatar/d22eb460ecab37fcd7205e6a3c55c228?s=200&r=X&d=",
|
data: {
|
||||||
},
|
profile: {
|
||||||
token
|
name: "Paul",
|
||||||
|
avatar: "https://sdn.geekzu.org/avatar/d22eb460ecab37fcd7205e6a3c55c228?s=200&r=X&d=",
|
||||||
|
},
|
||||||
|
token
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
import { useContext } from "@midwayjs/hooks";
|
import { useContext } from "@midwayjs/hooks";
|
||||||
import { CustomStrategy, PassportStrategy } from '@midwayjs/passport';
|
import { CustomStrategy, PassportStrategy } from "@midwayjs/passport";
|
||||||
import { Strategy, ExtractJwt } from 'passport-jwt';
|
import { Strategy, ExtractJwt } from "passport-jwt";
|
||||||
import { Config } from '@midwayjs/decorator';
|
import { Config } from "@midwayjs/decorator";
|
||||||
|
|
||||||
@CustomStrategy()
|
@CustomStrategy()
|
||||||
export class JwtStrategy extends PassportStrategy(
|
export class JwtStrategy extends PassportStrategy(
|
||||||
Strategy,
|
Strategy,
|
||||||
'jwt'
|
"jwt"
|
||||||
) {
|
) {
|
||||||
@Config('jwt')
|
@Config("jwt")
|
||||||
jwtConfig;
|
jwtConfig: any;
|
||||||
|
|
||||||
async validate(payload) {
|
async validate(payload) {
|
||||||
console.log('payload', payload);
|
console.log("payload", payload);
|
||||||
|
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue