4

ASP.NET MVC の代わりに Nancy を使用して、非常に単純なスパイクを実装しようとしています。

ユーザー名 (パスワードなし) を取得し、更新を必要とせずに同じログイン ページに意味のあるエラー メッセージを表示する必要があります。ログインが成功した場合、応答には移動先の URL が含まれます。

応答の POCO は次のようになります。

public class LoginResponseModel
{
    public bool IsSuccess { get; set; }
    public string RedirectUrl { get; set; }
    public string ErrorMessage { get; set; }
}

ログイン要求の JS ハンドラー:

$.ajax({
        url: '/login',
        type: "POST",
        data: { UserName: username }
    }).done(function (response) {
        if (response.IsSuccess) {
            showSuccess();
            document.location.href = response.RedirectUrl;
            return;
        }
        showError(response.ErrorMessage);
    }).fail(function (msg) {
        showError("Unable to process login request: " + msg.statusText);
    });

私が抱えている問題は、ナンシーのフォームベースの認証にあります。多かれ少なかれ同じことを行うさまざまなチュートリアルを 6 つ紹介し、Nancy 認証のデモも確認しました。LoginAndRedirectそれらすべてに共通していることの 1 つは、拡張メソッドに依存していることです。リダイレクトを返したくありません。ログイン試行の結果を返し、クライアントにナビゲーションを処理させたい。

私が使用している IUserMapper 実装:

public class UserMapper : IUserMapper
{
     public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
     {
        // Don't care who at this point, just want ANY user...
        return AuthenticatedUser {UserName = "admin"};
     }
}

私の LoginModule アクションの関連部分:

var result = _userMapper.ValidateUser(input.AccessCode);

if (result.Guid != null) this.Login(UserMapper.GUID_ADMIN, expiry);

return Response.AsJson(result.Response);

ただし、後続のリクエストContext.CurrentUserでは常に null です。

次のメソッドを Nancy.Demo.Authentication.Forms サンプルに追加すると、自分のプロジェクトで見られる動作が再現され、LoginWithoutRedirect が期待どおりに機能しないと思い込んでしまいます。

Get["/login/{name}"] = x =>
{
    Guid? userGuid = UserDatabase.ValidateUser(x.Name, "password");
    this.LoginWithoutRedirect(userGuid.Value, DateTime.Now.AddYears(2));
    return "Logged in as " + x.Name + " now <a href='~/secure'>see if it worked</a>";
};
4

2 に答える 2

3

Context.CurrentUser問題は、FormsAuthentication が応答を返さない場合に設定されない Cookie に依存していることが判明しましたNancyModule.Login()

var result = _userMapper.ValidateUser(input.AccessCode);             
if (result.IsSuccess) {
     this.LoginWithoutRedirect(result.Guid);
}
return Response.AsJson(result);

この例では、LoginWithoutRedirect呼び出しはResponseCookie が設定されたオブジェクトを返します。Ajax シナリオでこれを処理するには、クラスに AuthToken プロパティを追加し、次LoginAjaxResponseのように Cookie を渡す必要がありました。

var result = _userMapper.ValidateUser(input.AccessCode);             
var response = Response.AsJson(result);
if (result.IsSuccess) {
     var authResult = this.LoginWithoutRedirect(result.Guid);
     result.AuthToken = authResult.Cookies[0].Value;
}
return Response.AsJson(result);

クライアントでは、Ajax 応答ハンドラーが次のように変更されます ( jQuery cookie プラグインの使用を想定:

$.ajax({
    url: '/login',
    type: "POST",
    data: { UserName: username }
    }).done(function (response) {
    if (response.IsSuccess) {
        showSuccess();
        $.cookie("_ncfa", response.AuthToken); // <-- the magic happens here
        document.location.href = response.RedirectUrl;
        return;
    }
    showError(response.ErrorMessage);
}).fail(function (msg) {
   showError("Unable to process login request: " + msg.statusText);
});

AuthToken は、暗号化および base64 エンコードされた GUID です。this.RequiresAuthentication()有効になっている後続のリクエストでは、最初にこの認証トークン Cookie がチェックされます。

  • UserMapper「_ncfa 」Cookie が存在しない場合、GetUserFromIdentifier()は呼び出されません。

  • Context.Request.Cookies["_ncfa"]base64 でデコードおよび暗号化解除したときに、 の値が有効な GUID にならない場合、GetUserFromIdentifier()は呼び出されません。

  • GetUserFromIdentifier()呼び出されない場合はContext.CurrentUser設定されません。

実際の例のソースが必要な場合は、GitHubにあります。

于 2013-09-27T04:25:00.993 に答える