Skip to content

Commit dff9fd2

Browse files
committed
升级支持 react router v6 & v7 版本
1 parent f250914 commit dff9fd2

File tree

3 files changed

+57
-49
lines changed

3 files changed

+57
-49
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ rsr 是 react security router 的简写,一个基于 react router 实现路由
1515

1616
# 版本兼容
1717

18-
注意:不兼容 react router 7 版本,在 v7 😒 版本上的 `useBlocker` 逻辑变更了,暂时不考虑兼容。
18+
注意:目前只兼容 react router v6 & v7 版本,其它的版本,暂时不考虑兼容。
1919

2020
# 简单例子
2121

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@lanaqi/rsr",
3-
"version": "0.0.1-rc.0",
3+
"version": "0.0.1-rc.1",
44
"type": "module",
55
"exports": {
66
".": {
@@ -49,18 +49,18 @@
4949
"devDependencies": {
5050
"@biomejs/biome": "^1.9.4",
5151
"@rsbuild/plugin-react": "^1.1.1",
52-
"@rslib/core": "^0.5.5",
53-
"@types/react": "^18.3.19",
54-
"@types/react-dom": "^18.3.5",
55-
"react": "^18.3.1",
56-
"react-dom": "^18.3.1",
57-
"react-router-dom": "^6.30.0",
52+
"@rslib/core": "^0.6.8",
53+
"@types/react": "^19.1.3",
54+
"@types/react-dom": "^19.1.3",
55+
"react": "^19.1.0",
56+
"react-dom": "^19.1.0",
57+
"react-router-dom": "^7.5.3",
5858
"typescript": "^5.8.2"
5959
},
6060
"peerDependencies": {
6161
"react": ">=17.0.0",
6262
"react-dom": ">=17.0.0",
63-
"react-router-dom": "^6.0.0"
63+
"react-router-dom": "^6.0.0 || ^7.0.0"
6464
},
6565
"private": false,
6666
"publishConfig": {

src/security/blocker.tsx

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,105 +9,108 @@ import { type SecurityBundler, SecurityProvider, useSecurityContext } from './pr
99
* @constructor
1010
*/
1111
export function SecurityBlocker({ children }: PropsWithChildren) {
12-
const { context, manager, guarder } = useSecurityContext();
13-
if (manager.isDisabled()) {
12+
const { context, manager, guarder } = useSecurityContext(); // 获取安全上下文
13+
if (manager.isDisabled()) { // 如果管理器设置了禁用
1414
return <>{children}</>;
1515
}
16-
const blocker = useBlocker(({ currentLocation, nextLocation }) => {
16+
const blocker = useBlocker(({ currentLocation, nextLocation }) => { // 获取阻断器
1717
return currentLocation.pathname !== nextLocation.pathname; // 当前位置的路径值不等于下个位置的路径值
1818
});
1919
const [guarded, setGuarded] = useState<boolean>(false); // 被守护的
2020
const [nextPath, setNextPath] = useState<AccessPath>(useLocation()); // 下个路径
2121
const [firstAccess, setFirstAccess] = useState<boolean>(true); // 首次访问
2222
const [firstHandle, setFirstHandle] = useState<boolean>(true); // 首次处理
23-
const [firstSignature, setFirstSignature] = useState<number>(1); // 首次签名计数
24-
const [handleDecision, setHandleDecision] = useState<boolean>(false); // 处理决策
23+
const [countSignature, setCountSignature] = useState<number>(1); // 首次签名计数
24+
const [handledDecision, setHandledDecision] = useState<boolean>(false); // 是否需要处理决策
2525
const [beforeDecision, setBeforeDecision] = useState<AccessDecision | undefined>(undefined); // 之前决策
2626
const [currentDecision, setCurrentDecision] = useState<AccessDecision | undefined>(undefined); // 当前决策
27-
const [executeBlock, setExecuteBlock] = useState<boolean>(false); // 执行阻断
27+
const [securityBlock, setSecurityBlock] = useState<boolean>(false); // 执行安全阻断
28+
const [executableBlocked, setExecutableBlocked] = useState<boolean>(true); // 可执行已阻断
2829
useEffect(() => {
29-
if (blocker.state === 'blocked') {
30-
const recorder = context.getRecorder();
30+
if (blocker.state === 'blocked' && executableBlocked) {
31+
let isProceed: boolean; // 是否执行处理
32+
const recorder = context.getRecorder(); // 获取记录器
3133
const stayPath = recorder.getAllowPath(); // 停留路径
3234
const blockPath: AccessPath = blocker.location; // 阻断路径
3335
let guardBlocked = false;
34-
if (executeBlock) {
36+
if (securityBlock) {
3537
guardBlocked = guarder.guardBlock(blockPath); // 守护阻断
3638
}
3739
if (guardBlocked) {
38-
blocker.reset();
39-
setNextPath(blockPath); // 设置下个路径(当前是没有使用到的,也许后续扩展有可能会使用到)
40-
setHandleDecision(false); // 设置需要处理决策
40+
setHandledDecision(false); // 设置无需处理决策
4141
setCurrentDecision(undefined); // 设置当前决策
42+
isProceed = false; // 拒绝访问
4243
} else {
4344
if (!beforeDecision) {
4445
guarder.guardBefore(blockPath); // 守护之前
4546
}
4647
const blockedDecision = guarder.guardDecision(blockPath); // 守护决策
47-
if (blockedDecision === AccessDecision.allowAccess) {
48-
const isDiff = !!stayPath && stayPath.pathname !== blockPath.pathname; // 该逻辑始终为:true,以防其它覆盖则需要多一次判断
49-
if (isDiff) {
50-
guarder.permitBefore(stayPath, blockPath);
51-
}
52-
blocker.proceed();
53-
if (isDiff) {
54-
guarder.permitAfter(stayPath, blockPath);
55-
}
56-
} else {
57-
blocker.reset();
58-
}
59-
setNextPath(blockPath); // 设置下个路径
60-
setHandleDecision(true); // 设置需要处理决策
48+
setHandledDecision(true); // 设置需要处理决策
6149
setCurrentDecision(blockedDecision); // 设置当前决策
50+
isProceed = blockedDecision === AccessDecision.allowAccess;
51+
}
52+
setNextPath(blockPath); // 设置下个路径
53+
setExecutableBlocked(false); // 标记不可执行已阻断
54+
if (isProceed) {
55+
const isDiff = !!stayPath && stayPath.pathname !== blockPath.pathname; // 该逻辑始终为:true,以防其它覆盖则需要多一次判断
56+
if (isDiff) {
57+
guarder.permitBefore(stayPath, blockPath);
58+
}
59+
blocker.proceed(); // 在 v7 版本该逻辑是异步的
60+
if (isDiff) {
61+
guarder.permitAfter(stayPath, blockPath);
62+
}
63+
} else {
64+
blocker.reset();
6265
}
6366
} else if (blocker.state === 'unblocked') {
6467
// 如果需要处理决策同时设置了当前决策
65-
if (handleDecision && currentDecision) {
68+
if (handledDecision && currentDecision) {
6669
let navNext: boolean; // 是否导航下个
6770
const behave = guarder.guardHandle(currentDecision, beforeDecision); // 守护处理
6871
switch (behave) {
6972
// 重新决策
7073
case AccessBehave.reDecision: {
7174
setBeforeDecision(currentDecision); // 设置之前决策
72-
setExecuteBlock(false);
75+
setSecurityBlock(false);
7376
navNext = true;
7477
break;
7578
}
7679
// 跳转导航
7780
case AccessBehave.goNavigate: {
7881
setBeforeDecision(undefined); // 设置之前决策
7982
navNext = false;
80-
setExecuteBlock(false);
83+
setSecurityBlock(false);
8184
break;
8285
}
8386
// 忽略操作
8487
case AccessBehave.doNothing:
8588
default: {
8689
setBeforeDecision(undefined); // 清理之前决策
8790
navNext = false;
88-
setExecuteBlock(true);
91+
setSecurityBlock(true);
8992
break;
9093
}
9194
}
9295
// 如果是首次处理同时是没有签名的以及需要重新决策的
9396
if (firstHandle && currentDecision === AccessDecision.notSignature && behave === AccessBehave.reDecision) {
9497
// 如果多次重新决策签名依旧再次需要签名的则拒绝访问
95-
if (firstSignature >= 3) {
98+
if (countSignature >= 3) {
9699
setFirstHandle(false); // 标记不再是首次处理
97100
setBeforeDecision(AccessDecision.notSignature); // 设置之前决策为没有签名
98-
setHandleDecision(true); // 设置需要处理决策
101+
setHandledDecision(true); // 设置需要处理决策
99102
setCurrentDecision(AccessDecision.accessDenied); // 设置当前决策为拒绝访问
100103
} else {
101104
// 基于当前路径再执行一次
102105
const signDecision = guarder.guardDecision(nextPath); // 再一次决策
103-
setHandleDecision(true); // 设置需要处理决策
106+
setHandledDecision(true); // 设置需要处理决策
104107
setBeforeDecision(undefined); // 设置之前决策为空
105108
setCurrentDecision(signDecision); // 设置当前决策
106-
setFirstSignature(firstSignature + 1); // 签名计数
109+
setCountSignature(countSignature + 1); // 签名计数
107110
}
108111
} else {
109112
setFirstHandle(false); // 标记不再是首次处理
110-
setHandleDecision(false); // 清理处理决策
113+
setHandledDecision(false); // 设置无需处理决策
111114
setCurrentDecision(undefined); // 清理当前决策
112115
// 如果导航下个
113116
if (navNext) {
@@ -117,18 +120,23 @@ export function SecurityBlocker({ children }: PropsWithChildren) {
117120
setGuarded(true);
118121
}
119122
}
120-
}
121-
// 如果是首次访问
122-
else if (firstAccess) {
123+
} else if (firstAccess) { // 如果是首次访问
123124
// 基于当前路径执行一次
124125
guarder.guardBefore(nextPath); // 守护之前
125126
const firstDecision = guarder.guardDecision(nextPath); // 守护决策
126127
setFirstAccess(false); // 标记非首次访问
127-
setHandleDecision(true); // 设置需要处理决策
128+
setHandledDecision(true); // 设置需要处理决策
128129
setCurrentDecision(firstDecision); // 设置当前决策
129130
}
131+
if (!executableBlocked) {
132+
setExecutableBlocked(true); // 标记已可执行已阻断
133+
}
130134
}
131-
}, [blocker, context, guarder, nextPath, firstAccess, firstHandle, firstSignature, handleDecision, beforeDecision, currentDecision, executeBlock]);
135+
}, [
136+
blocker, context, guarder,
137+
nextPath, firstAccess, firstHandle, countSignature,
138+
handledDecision, beforeDecision, currentDecision, securityBlock, executableBlocked
139+
]);
132140
if (!guarded) {
133141
return <></>;
134142
}

0 commit comments

Comments
 (0)