我一直在研究一个简单的 API 示例,它是带有身份验证的 ServiceStack Hello World 示例的修改版本。概念证明的目标是创建一个 RESTful API,其中包含需要身份验证的服务,这些服务完全可以通过 Ajax 从几个不同的 Web 项目中访问。
我已经阅读了 wiki 并实现了身份验证和授权以及实现 CORS(许多结果 [对不起,没有足够的信任指向相关链接])。此时,我的 Hello 服务可以使用覆盖 CredentialsAuthProvider 和自定义用户会话对象的自定义身份验证机制进行身份验证。我创建或借用了一个简单的测试应用程序(一个完全独立的项目来模拟我们的需求),可以进行身份验证,然后调用 Hello 服务,传递一个名称,并通过一个单一的接收“Hello Fred”响应浏览器会话。也就是说,我可以调用 url 中的 /auth/credentials 路径,传递用户名和 id,并收到正确的响应。然后我可以将 url 更新为 /hello/fred 并接收有效响应。
我的理解失败是如何为所有 ajax 调用实现身份验证。我在下面的初始登录工作正常。无论我做什么,我尝试通过 ajax 调用经过身份验证的服务,我要么收到 OPTIONS 404 错误或 Not Found 错误,要么 Origin http // localhost:12345 (pseudo-link) is not allowed by Access-Control-Allow -产地等
我需要走这条路吗?
对不起,如果这令人困惑。如果需要,我可以提供更多详细信息,但认为这可能足以帮助知识渊博的人帮助我缺乏理解。
function InvokeLogin() {
var Basic = new Object();
Basic.UserName = "MyUser";
Basic.password = "MyPass";
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(Basic),
url: "http://localhost:58795/auth/credentials",
success: function (data, textStatus, jqXHR) {
alert('Authenticated! Now you can run Hello Service.');
},
error: function(xhr, textStatus, errorThrown) {
var data = $.parseJSON(xhr.responseText);
if (data === null)
alert(textStatus + " HttpCode:" + xhr.status);
else
alert("ERROR: " + data.ResponseStatus.Message + (data.ResponseStatus.StackTrace ? " \r\n Stack:" + data.ResponseStatus.StackTrace : ""));
}
});
}
编辑:
根据 Stefan 提供的回复和链接,我做了一些更改:
我的配置 (注意:我正在使用自定义身份验证和会话对象,并且一切正常。)
public override void Configure(Funq.Container container)
{
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new CustomCredentialsAuthProvider(),
}));
base.SetConfig(new EndpointHostConfig
{
GlobalResponseHeaders = {
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
{ "Access-Control-Allow-Headers", "Content-Type, Authorization" },
},
DefaultContentType = "application/json"
});
Plugins.Add(new CorsFeature());
this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
//Handles Request and closes Responses after emitting global HTTP Headers
if (httpReq.HttpMethod == "OPTIONS")
httpRes.EndRequest(); // extension method
});
Routes
.Add<Hello>("/Hello", "GET, OPTIONS");
container.Register<ICacheClient>(new MemoryCacheClient());
var userRep = new InMemoryAuthRepository();
container.Register<IUserAuthRepository>(userRep);
}
我的简单问候服务
[EnableCors]
public class HelloService : IService
{
[Authenticate]
public object GET(Hello request)
{
Looks strange when the name is null so we replace with a generic name.
var name = request.Name ?? "John Doe";
return new HelloResponse { Result = "Hello, " + name };
}
}
在上面进行登录调用之后,我随后调用 Hello 服务现在产生 401 错误,这是进度,尽管不是我需要的。( Jquery.support.cors= true 在我的脚本文件中设置。)
function helloService() {
$.ajax({
type: "GET",
contentType: "application/json",
dataType: "json",
url: "http://localhost:58795/hello",
success: function (data, textStatus, jqXHR) {
alert(data.Result);
},
error: function (xhr, textStatus, errorThrown) {
var data = $.parseJSON(xhr.responseText);
if (data === null)
alert(textStatus + " HttpCode:" + xhr.status);
else
alert("ERROR: " + data.ResponseStatus.Message +
(data.ResponseStatus.StackTrace ? " \r\n Stack:" + data.ResponseStatus.StackTrace : ""));
}
});
}
同样,如果我首先正确调用 /auth/credentials,然后再调用 /hello,这在 RESTConsole 中有效。
最终编辑 在 Stefan 的建议下,包括许多其他链接,我终于能够得到这个工作。除了 Stefan 的代码之外,我还必须进行一项额外的修改:
Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization"));
迎接下一个挑战:更新 Jonas Eriksson 的 CustomAuthenticateAttibute 代码(似乎使用的是旧版本的 ServiceStack,因为一些功能不再可用。
再次感谢斯特凡!!