34 lines
1.1 KiB
Dart
34 lines
1.1 KiB
Dart
|
|
// 功能描述:提供鉴权页面地址构造与站内回跳地址校验。
|
|||
|
|
// 版本:1.0.0
|
|||
|
|
|
|||
|
|
/// 构造登录或注册地址,并安全携带原目标页和会话失效原因。
|
|||
|
|
String buildAuthLocation(
|
|||
|
|
String authPath, {
|
|||
|
|
String? redirectTarget,
|
|||
|
|
bool sessionExpired = false,
|
|||
|
|
}) {
|
|||
|
|
final safeTarget = sanitizeRedirectTarget(redirectTarget);
|
|||
|
|
final query = <String, String>{
|
|||
|
|
'redirect': ?safeTarget,
|
|||
|
|
if (sessionExpired) 'reason': 'expired',
|
|||
|
|
};
|
|||
|
|
return Uri(
|
|||
|
|
path: authPath,
|
|||
|
|
queryParameters: query.isEmpty ? null : query,
|
|||
|
|
).toString();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 只接受站内绝对路径,阻止外部地址和鉴权页之间形成重定向循环。
|
|||
|
|
String? sanitizeRedirectTarget(String? value) {
|
|||
|
|
final candidate = value?.trim() ?? '';
|
|||
|
|
if (candidate.isEmpty) return null;
|
|||
|
|
|
|||
|
|
final uri = Uri.tryParse(candidate);
|
|||
|
|
if (uri == null || uri.hasScheme || uri.hasAuthority || !uri.path.startsWith('/')) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
if (uri.path.startsWith('//') || uri.path.contains(r'\')) return null;
|
|||
|
|
if (uri.path == '/login' || uri.path == '/register') return null;
|
|||
|
|
return uri.toString();
|
|||
|
|
}
|