我有一个使用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; }
}
但是,当我在登录视图页面上填写用户名和密码并将这些用户名和密码POST到SiteLoginService时,BasicAuthProvider总是抛出HttpError:“无效的BasicAuth凭据”。可能是因为Web浏览器没有填写Basic auth标头,但我不知道如何使用填写的用户名和密码进行身份验证。
如何根据与现有REST API一起使用的AuthProvider正确验证网站用户?
答案 0 :(得分:1)
如果您传递的是用户名&amp;密码作为帖子,然后因为您怀疑您没有进行基本身份验证。
This article说明了如何使用JavaScript进行基本身份验证。来自文章:
function login() {
var username = document.getElementById(this.id + "-username").value;
var password = document.getElementById(this.id + "-password").value;
this.http.open("get", this.action, false, username, password);
this.http.send("");
if (http.status == 200) {
document.location = this.action;
} else {
alert("Incorrect username and/or password.");
}
return false;
}
ServiceStack还支持其他形式的身份验证,包括通过POST发送用户名和密码(如果这是您想要的)。如果您解释了您的要求,我们可以提供一些建议。
答案 1 :(得分: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
})
所以我在登录表单中将操作指定为/ auth / credentials,同时提供所需的UserName和Password字段。
<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>
当表单发布时,它会正确地命中验证代码流(TryAuthenticate
中调用IUserAuthRepository
并返回true)。
最终请求收到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>
继续属性在服务中从其模型的Redirect属性中填充。