1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System . Security . Cryptography ;
4
5
using System . Text . Encodings . Web ;
5
6
using Microsoft . AspNetCore . Builder ;
6
7
using Microsoft . AspNetCore . DataProtection ;
7
8
using Microsoft . AspNetCore . Http ;
8
9
using Microsoft . AspNetCore . Routing ;
9
10
using Microsoft . Extensions . DependencyInjection ;
11
+ using Microsoft . Extensions . Logging ;
12
+ using Microsoft . Extensions . Options ;
10
13
11
14
namespace Microsoft . AspNetCore . Components . Endpoints ;
12
15
13
- internal static class OpaqueRedirection
16
+ internal partial class OpaqueRedirection
14
17
{
15
18
// During streaming SSR, a component may try to perform a redirection. Since the response has already started
16
19
// this can only work if we communicate the redirection back via some command that can get handled by JS,
@@ -38,7 +41,9 @@ internal static class OpaqueRedirection
38
41
public static string CreateProtectedRedirectionUrl ( HttpContext httpContext , string destinationUrl )
39
42
{
40
43
var protector = CreateProtector ( httpContext ) ;
41
- var protectedUrl = protector . Protect ( destinationUrl , TimeSpan . FromSeconds ( 10 ) ) ;
44
+ var options = httpContext . RequestServices . GetRequiredService < IOptions < RazorComponentsServiceOptions > > ( ) ;
45
+ var lifetime = options . Value . TemporaryRedirectionUrlValidityDuration ;
46
+ var protectedUrl = protector . Protect ( destinationUrl , lifetime ) ;
42
47
return $ "{ RedirectionEndpointBaseRelativeUrl } ?url={ UrlEncoder . Default . Encode ( protectedUrl ) } ";
43
48
}
44
49
@@ -53,7 +58,23 @@ public static void AddBlazorOpaqueRedirectionEndpoint(IEndpointRouteBuilder endp
53
58
}
54
59
55
60
var protector = CreateProtector ( httpContext ) ;
56
- var url = protector . Unprotect ( protectedUrl [ 0 ] ! ) ;
61
+ string url ;
62
+
63
+ try
64
+ {
65
+ url = protector . Unprotect ( protectedUrl [ 0 ] ! ) ;
66
+ }
67
+ catch ( CryptographicException ex )
68
+ {
69
+ if ( httpContext . RequestServices . GetService < ILogger < OpaqueRedirection > > ( ) is { } logger )
70
+ {
71
+ Log . OpaqueUrlUnprotectionFailed ( logger , ex ) ;
72
+ }
73
+
74
+ httpContext . Response . StatusCode = 400 ;
75
+ return Task . CompletedTask ;
76
+ }
77
+
57
78
httpContext . Response . Redirect ( url ) ;
58
79
return Task . CompletedTask ;
59
80
} ) ;
@@ -64,4 +85,10 @@ private static ITimeLimitedDataProtector CreateProtector(HttpContext httpContext
64
85
var dataProtectionProvider = httpContext . RequestServices . GetRequiredService < IDataProtectionProvider > ( ) ;
65
86
return dataProtectionProvider . CreateProtector ( RedirectionDataProtectionProviderPurpose ) . ToTimeLimitedDataProtector ( ) ;
66
87
}
88
+
89
+ public static partial class Log
90
+ {
91
+ [ LoggerMessage ( 1 , LogLevel . Information , "Opaque URL unprotection failed." , EventName = "OpaqueUrlUnprotectionFailed" ) ]
92
+ public static partial void OpaqueUrlUnprotectionFailed ( ILogger < OpaqueRedirection > logger , Exception exception ) ;
93
+ }
67
94
}
0 commit comments