我一直在研究一个简单的 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 错误或未找到错误,要么 Access-Control-Allow 不允许 Origin http // localhost:12345 (pseudo-link) -产地等
我需要去吗这条路线?
抱歉,如果这令人困惑。如果需要,我可以提供更多详细信息,但我认为这可能足以帮助知识渊博的人来帮助我解决缺乏理解的问题。
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 : ""));
}
});
}
EDIT:
根据 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 的代码之外,我还必须进行一项额外的修改:
Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization"));
迎接下一个挑战:更新 Jonas Eriksson 的 CustomAuthenticateAttibute 代码(该代码似乎使用旧版本的 ServiceStack,因为一些功能不再可用。
再次感谢斯蒂芬!