Skip to content

Commit 6ff4349

Browse files
committed
Logout when connection gets closed
Closes #93 Differences between this change and the PR: - No changes to IFtpUser - No `AuthorityId` - No changes to `IUnixFileSystemEntry` - No `PrincipalUser` - No changes to `FtpServerOptions` - PASV configuration is already configurable through `PasvListenerOptions` - LogOut became LogOutAsync in `IMembershipProviderAsync`
1 parent d0887cd commit 6ff4349

17 files changed

Lines changed: 239 additions & 30 deletions

File tree

samples/TestFtpServer/CustomMembershipProvider.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// </copyright>
44

55
using System.Security.Claims;
6+
using System.Threading;
67
using System.Threading.Tasks;
78

89
using FubarDev.FtpServer.AccountManagement;
@@ -12,10 +13,13 @@ namespace TestFtpServer
1213
/// <summary>
1314
/// Custom membership provider
1415
/// </summary>
15-
public class CustomMembershipProvider : IMembershipProvider
16+
public class CustomMembershipProvider : IMembershipProviderAsync
1617
{
1718
/// <inheritdoc />
18-
public Task<MemberValidationResult> ValidateUserAsync(string username, string password)
19+
public Task<MemberValidationResult> ValidateUserAsync(
20+
string username,
21+
string password,
22+
CancellationToken cancellationToken)
1923
{
2024
if (username != "tester" || password != "testing")
2125
{
@@ -38,5 +42,17 @@ public Task<MemberValidationResult> ValidateUserAsync(string username, string pa
3842
user));
3943

4044
}
45+
46+
/// <inheritdoc />
47+
public Task LogOutAsync(ClaimsPrincipal principal, CancellationToken cancellationToken)
48+
{
49+
return Task.CompletedTask;
50+
}
51+
52+
/// <inheritdoc />
53+
public Task<MemberValidationResult> ValidateUserAsync(string username, string password)
54+
{
55+
return ValidateUserAsync(username, password, CancellationToken.None);
56+
}
4157
}
4258
}

src/FubarDev.FtpServer.Abstractions/AccountManagement/AnonymousMembershipProvider.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
using System.Collections.Generic;
99
using System.Security.Claims;
10+
using System.Threading;
1011
using System.Threading.Tasks;
1112

1213
using FubarDev.FtpServer.AccountManagement.Anonymous;
@@ -16,7 +17,7 @@ namespace FubarDev.FtpServer.AccountManagement
1617
/// <summary>
1718
/// Allow any anonymous login.
1819
/// </summary>
19-
public class AnonymousMembershipProvider : IMembershipProvider
20+
public class AnonymousMembershipProvider : IMembershipProviderAsync
2021
{
2122
private readonly IAnonymousPasswordValidator _anonymousPasswordValidator;
2223

@@ -68,7 +69,10 @@ public static ClaimsPrincipal CreateAnonymousPrincipal(string? email)
6869
}
6970

7071
/// <inheritdoc/>
71-
public Task<MemberValidationResult> ValidateUserAsync(string username, string password)
72+
public Task<MemberValidationResult> ValidateUserAsync(
73+
string username,
74+
string password,
75+
CancellationToken cancellationToken)
7276
{
7377
if (string.Equals(username, "anonymous"))
7478
{
@@ -83,5 +87,17 @@ public Task<MemberValidationResult> ValidateUserAsync(string username, string pa
8387

8488
return Task.FromResult(new MemberValidationResult(MemberValidationStatus.InvalidLogin));
8589
}
90+
91+
/// <inheritdoc />
92+
public Task LogOutAsync(ClaimsPrincipal principal, CancellationToken cancellationToken)
93+
{
94+
return Task.CompletedTask;
95+
}
96+
97+
/// <inheritdoc />
98+
public Task<MemberValidationResult> ValidateUserAsync(string username, string password)
99+
{
100+
return ValidateUserAsync(username, password, CancellationToken.None);
101+
}
86102
}
87103
}

src/FubarDev.FtpServer.Abstractions/AccountManagement/IMembershipProvider.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// <author>Mark Junker</author>
66
//-----------------------------------------------------------------------
77

8+
using System;
89
using System.Threading.Tasks;
910

1011
namespace FubarDev.FtpServer.AccountManagement
@@ -23,6 +24,9 @@ public interface IMembershipProvider
2324
/// <param name="username">The user name.</param>
2425
/// <param name="password">The password.</param>
2526
/// <returns>The result of the validation.</returns>
26-
Task<MemberValidationResult> ValidateUserAsync(string username, string password);
27+
[Obsolete("Use IMembershipProviderAsync.ValidateUserAsync")]
28+
Task<MemberValidationResult> ValidateUserAsync(
29+
string username,
30+
string password);
2731
}
2832
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// <copyright file="IMembershipProviderAsync.cs" company="Fubar Development Junker">
2+
// Copyright (c) Fubar Development Junker. All rights reserved.
3+
// </copyright>
4+
5+
using System.Security.Claims;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace FubarDev.FtpServer.AccountManagement
10+
{
11+
/// <summary>
12+
/// Membership provider interface.
13+
/// </summary>
14+
/// <remarks>
15+
/// This interface must be implemented to allow the username/password authentication.
16+
/// </remarks>
17+
public interface IMembershipProviderAsync : IMembershipProvider
18+
{
19+
/// <summary>
20+
/// Validates if the combination of <paramref name="username"/> and <paramref name="password"/> is valid.
21+
/// </summary>
22+
/// <param name="username">The user name.</param>
23+
/// <param name="password">The password.</param>
24+
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
25+
/// <returns>The result of the validation.</returns>
26+
Task<MemberValidationResult> ValidateUserAsync(
27+
string username,
28+
string password,
29+
CancellationToken cancellationToken = default);
30+
31+
/// <summary>
32+
/// Logout of the given <paramref name="principal"/>.
33+
/// </summary>
34+
/// <param name="principal">The principal to be logged out.</param>
35+
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
36+
/// <returns>The task.</returns>
37+
Task LogOutAsync(
38+
ClaimsPrincipal principal,
39+
CancellationToken cancellationToken = default);
40+
}
41+
}

src/FubarDev.FtpServer.Abstractions/Authorization/Actions/FillConnectionAccountDataAction.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public Task AuthorizedAsync(IAccountInformation accountInformation, Cancellation
4040
authInfoFeature.User = accountInformation.User;
4141
#pragma warning restore 618
4242
authInfoFeature.FtpUser = accountInformation.FtpUser;
43+
authInfoFeature.MembershipProvider = accountInformation.MembershipProvider;
4344

4445
#pragma warning disable 618
4546
connection.Data.IsAnonymous = accountInformation.User is IAnonymousFtpUser;

src/FubarDev.FtpServer.Abstractions/Authorization/PasswordAuthorization.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,20 @@ public override async Task<IFtpResponse> HandlePassAsync(string password, Cancel
6666

6767
foreach (var membershipProvider in _membershipProviders)
6868
{
69-
var validationResult = await membershipProvider
70-
.ValidateUserAsync(_userName, password)
71-
.ConfigureAwait(false);
69+
#pragma warning disable 618
70+
var validationResult = membershipProvider is IMembershipProviderAsync membershipProviderAsync
71+
? await membershipProviderAsync
72+
.ValidateUserAsync(_userName, password, cancellationToken)
73+
.ConfigureAwait(false)
74+
: await membershipProvider
75+
.ValidateUserAsync(_userName, password)
76+
.ConfigureAwait(false);
77+
#pragma warning restore 618
7278
if (validationResult.IsSuccess)
7379
{
74-
var accountInformation = new DefaultAccountInformation(validationResult.FtpUser);
80+
var accountInformation = new DefaultAccountInformation(
81+
validationResult.FtpUser,
82+
membershipProvider);
7583

7684
foreach (var authorizationAction in _authorizationActions)
7785
{
@@ -132,8 +140,11 @@ public UnauthenticatedUser(string name)
132140

133141
private class DefaultAccountInformation : IAccountInformation
134142
{
135-
public DefaultAccountInformation(ClaimsPrincipal user)
143+
public DefaultAccountInformation(
144+
ClaimsPrincipal user,
145+
IMembershipProvider membershipProvider)
136146
{
147+
MembershipProvider = membershipProvider;
137148
FtpUser = user;
138149
#pragma warning disable 618
139150
#pragma warning disable 612
@@ -148,6 +159,9 @@ public DefaultAccountInformation(ClaimsPrincipal user)
148159

149160
/// <inheritdoc />
150161
public ClaimsPrincipal FtpUser { get; }
162+
163+
/// <inheritdoc />
164+
public IMembershipProvider MembershipProvider { get; }
151165
}
152166
}
153167
}

src/FubarDev.FtpServer.Abstractions/Commands/DefaultFtpCommandDispatcher.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,12 @@
44

55
using System;
66
using System.Collections.Generic;
7-
using System.ComponentModel.DataAnnotations;
8-
using System.Diagnostics;
97
using System.Linq;
10-
using System.Net.Sockets;
118
using System.Threading;
129
using System.Threading.Tasks;
1310

1411
using FubarDev.FtpServer.Features;
1512
using FubarDev.FtpServer.Features.Impl;
16-
using FubarDev.FtpServer.FileSystem.Error;
1713
using FubarDev.FtpServer.ServerCommands;
1814

1915
using JetBrains.Annotations;

src/FubarDev.FtpServer.Abstractions/ConnectionExtensions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
using System;
66
using System.ComponentModel.DataAnnotations;
7-
using System.Diagnostics;
87
#if !NETSTANDARD1_3
98
using System.Net.Sockets;
109
#endif

src/FubarDev.FtpServer.Abstractions/Features/IAuthorizationInformationFeature.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,10 @@ public interface IAuthorizationInformationFeature
2424
/// Gets or sets the current user.
2525
/// </summary>
2626
ClaimsPrincipal? FtpUser { get; set; }
27+
28+
/// <summary>
29+
/// Gets or sets the membership provider that authenticated the <see cref="FtpUser"/>.
30+
/// </summary>
31+
IMembershipProvider? MembershipProvider { get; set; }
2732
}
2833
}

src/FubarDev.FtpServer.Abstractions/Features/Impl/AuthorizationInformationFeature.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,8 @@ internal class AuthorizationInformationFeature : IAuthorizationInformationFeatur
2020

2121
/// <inheritdoc />
2222
public ClaimsPrincipal? FtpUser { get; set; }
23+
24+
/// <inheritdoc />
25+
public IMembershipProvider? MembershipProvider { get; set; }
2326
}
2427
}

0 commit comments

Comments
 (0)