2

ServiceStack を使用して構築された REST API があります。REST API を呼び出すときに問題なく BasicAuthentication を使用しています ( を に登録しAuthFeatureていますBasicAuthProvider)。

現在、いくつかの HTML 管理ページを作成しようとしています。これらも認証する必要があります。

[Authenticate] 属性は /login ページにリダイレクトされるため、ログインを処理するために次の DTO と一致するサービスを作成しました。

    [DefaultView("Login")]
    public class SiteLoginService : EnshareServiceBase
    {
        public object Get(SiteLoginRequest req)
        {
            return new SiteLoginRequest();
        }

        public object Post(SiteLoginRequest req)
        {
            //I am trying to use the registered IAuthProvider, which is the BasicAuthProvider
            var authProvider = ResolveService<IAuthProvider>();
            authProvider.Authenticate(this, EnshareSession,
                                      new ServiceStack.ServiceInterface.Auth.Auth()
                                      {
                                          Password = req.Password,
                                          UserName = req.UserName
                                      });
            return HttpResult.Redirect(req.Redirect);
        }
    }

    [Route("/login")]
    public class SiteLoginRequest : IReturn<SiteLoginRequest>
    {
        public string Redirect { get; set; }
        public string Password { get; set; }
        public string UserName { get; set; }
    }

ただし、ログイン ビュー ページにユーザー名とパスワードを入力し、これらを SiteLoginService に POST すると、BasicAuthProvider は常に HttpError: "Invalid BasicAuth credentials" をスローします。おそらく、Web ブラウザーが Basic 認証ヘッダーに入力していないためですが、ユーザー名とパスワードを入力して認証する方法がわかりません。

既存の REST API で動作する AuthProvider に対してサイト ユーザーを適切に認証するにはどうすればよいですか?

4

2 に答える 2

1

AuthFeature に CredentialsAuthProvider も含める必要があると考えました。これにより、フォームを投稿する /auth/credentials サービスが公開されます。

        //this inherits the BasicAuthProvider and is used to authenticate the REST API calls
        var myCustomAuthProvider = new CustomAuthProvider(appSettings);
        var credentialsProvider = new CredentialsAuthProvider(appSettings);
        container.Register<IAuthProvider>(myCustomAuthProvider);
        container.Register<CredentialsAuthProvider>(credentialsProvider);
        var authFeature = new AuthFeature(() => new EnshareSession(new MongoTenantRepository()),
                                          new IAuthProvider[] {
                                                                  myCustomAuthProvider,
                                                                  credentialsProvider 
                                                               })

そのため、必要な UserName フィールドと Password フィールドを提供しながら、ログイン フォームでアクションを /auth/credentials として指定しました。

        <form action="/auth/credentials" method="post">
            <p class="entryfield">
                @Html.LabelFor(m => m.UserName, "Login name:")
                @Html.TextBoxFor(u => u.UserName)
            </p>
            <p class="entryfield">
                @Html.LabelFor(m => m.Password)
                @Html.PasswordFor(m => m.Password)
            </p>
            <input class="formbutton" type="submit" value="Login" />
        </form>

フォームが投稿されると、認証コード フローに適切にヒットします ( TryAuthenticatemy で呼び出され、IUserAuthRepositorytrue を返します)。

最終的に、リクエストは 302 を受け取り、/login のログイン フォームが再表示されます。

    HTTP/1.1 302 Found
    Server: ASP.NET Development Server/10.0.0.0
    Date: Wed, 30 Oct 2013 08:15:54 GMT
    X-AspNet-Version: 4.0.30319
    X-Powered-By: ServiceStack/3,969 Win32NT/.NET
    Location: http://localhost:64944/login?redirect=%2fadmin
    Set-Cookie: X-UAId=3; expires=Sun, 30-Oct-2033 08:15:54 GMT; path=/; HttpOnly

セッション Cookie (X-AUId) を設定しており、ユーザーは適切に認証されています。Authenticate 属性で修飾されたサービスへの後続の Web ブラウザー要求は成功します。

したがって、唯一欠けている部分は、投稿後にユーザーが適切にリダイレクトされるようにする方法/auth/credentialsです。

リダイレクトが機能することを確認するには、Continue パラメーターが必要であることがわかりました。

したがって、ログイン フォームは次のようになります (モデルには ServiceStack の Auth クラスを再利用しました)。

    @inherits ViewPage<ServiceStack.ServiceInterface.Auth.Auth>
    @{

        Layout = "AdminLayout";
    }

    <form action="/auth/credentials" method="post">
        <p class="entryfield">
            @Html.LabelFor(m => m.UserName, "Login name:")
            @Html.TextBoxFor(u => u.UserName)
        </p>
        <p class="entryfield">
            @Html.LabelFor(m => m.Password)
            @Html.PasswordFor(m => m.Password)
        </p>
        @Html.HiddenFor(m => m.Continue)
        <input type="submit" value="Login" />
    </form>

Continue プロパティは、そのモデルの Redirect プロパティからサービスに取り込まれます。

于 2013-10-30T08:22:28.127 に答える