访问使用Ajax ServiceStack认证服务Ajax、ServiceStack

2023-09-10 13:36:09 作者:彼岸花﹏落败

我已经通过一个简单的API的例子打工,ServiceStack Hello World示例身份验证的修改版本。概念论证的目标是创建一个基于REST的API,它包含需要访问的身份验证服务,完全是通过阿贾克斯从几个不同的Web项目。

I've been working through a simple API example, a modified version of the ServiceStack Hello World example with authentication. The goal of the proof of concept is to create an a RESTful API that contains services requiring authentication accessible entirely through Ajax from several different web projects.

我读过维基的,实施,验证和授权和实施CORS(很多,结果[对不起,没有足够的名气指向相关链接])。在这一点上,我的你好服务可以鉴定其压倒CredentialsAuthProvider和定制用户会话对象的自定义的认证机制。我创建,或借来的,而不是一个简单的测试应用程序(一个完全独立的项目来模拟我们的需求),并可以进行身份​​验证,然后调入你好服务,传递一个名称,并通过一个单一的接收'你好弗雷德'回应浏览器会话。也就是说,我可以调用/认证/证书路径的网址,通过用户名和ID,并获得适当的反应。那么我可以更新网址/你好/弗雷德和接收有效响应。

I've read the wiki for, and implemented, Authentication and authorization and implementing CORS (many, results [sorry, not enough cred to point to the relevant link]). At this point, my Hello service can authenticate using a custom authentication mechanism which is over-riding CredentialsAuthProvider and a custom user session object. I've created, or borrowed, rather, a simple test application (an entirely separate project to simulate our needs) and can authenticate and then call into the Hello service, passing a name, and receive a 'Hello Fred' response through a single browser session. That is, I can call the /auth/credentials path in the url, passing the username and id, and receive a proper response. I can then update the url to /hello/fred and receive a valid response.

我的理解击穿是如何实现对所有Ajax调用的认证。我初次登录,下面,做工精细。无论我做什么,我试图通过AJAX调用验证的服务,我要么收到选项404错误或Not Found错误,或原产地的http //本地主机:12345(伪链接)不会被允许的访问控制,允许-Origin等。

My breakdown in understanding is how to implement the authentication for all ajax calls. My initial login, below, works fine. No matter what I do, my attempt to call the authenticated service via ajax, I either receive a OPTIONS 404 error or Not Found error, or Origin http // localhost:12345 (pseudo-link) is not allowed by Access-Control-Allow-Origin, etc.

我需要去this路线?

抱歉,如果这是令人困惑的。我可以提供,如果需要更多的细节,但认为这可能是足够的帮助的知识来帮助我缺乏了解。

Sorry if this is confusing. I can provide greater details if required, but think this might be sufficient help the knowledgeable to help my lack of understanding.

    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 : ""));
        }
    });
}

编辑:

,我做了一些改动:

我的配置(注意:我使用自定义的认证和会话对象,这是所有正常工作)

My Config (Note: I'm using custom authentication and session object and that is all working correctly.)

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);
}

我的简单的Hello服务

[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的设置在我的脚本文件。)

After making the login call, above, my subsequent call the Hello service is now yielding a 401 error, which is progress, though not where I need to be. (The Jquery.support.cors= true is set in my script file.)

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 : ""));
        }
    });
}

此外,这部作品在RESTConsole,如果我先调用/认证/凭据正确,然后按照与呼叫/你好。

Again, this works in the RESTConsole if I first make the call to /auth/credentials properly and then follow that up with a call to /hello.

最后修改 继Stefan的提醒,以下,包括很多环节,我终于能够得到这个工作。除了Stefan的code,我不得不做出一个额外的修改:

FINAL EDIT Following Stefan's advise, below, including many other links, I was finally able to get this working. In addition to Stefan's code, I had to make one additional modification:

Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization"));

在到下一个挑战:更新乔纳斯埃里克森的CustomAuthenticateAttibute code(这显然是利用ServiceStack较旧版本的一对夫妇的功能不再可用。

On to the next challenge: Updating Jonas Eriksson's CustomAuthenticateAttibute code (which appears to be using an older version of ServiceStack as a couple of functions are no longer available.

再次感谢史蒂芬!

推荐答案

这code对我的作品的基础上,维基文件自定义验证和授权

this code works for me, based on the Wiki documentation Custom authentication and authorization

code也是基于从社区资源的博客文章   CORS基本验证上ServiceStack与自定义验证

Code is based also in the blog post from Community Resources CORS BasicAuth on ServiceStack with custom authentication

有关基本身份验证,自定义提供

For Basic Authentication, a custom provider

   public class myAuthProvider : BasicAuthProvider
    {
           public myAuthProvider() : base() { }

       public override bool TryAuthenticate(IServiceBase authService, string userName, string  password)
    {
        //Add here your custom auth logic (database calls etc)
        //Return true if credentials are valid, otherwise false
        if (userName == "admin" && password == "test")
                      return true;
         else
               return false;

    }

    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        //Fill the IAuthSession with data which you want to retrieve in the app 
       //  the base AuthUserSession properties e.g
       session.FirstName = "It's me";
        //...   
       //  derived CustomUserSession properties e.g
        if(session is CustomUserSession)
       ((CustomUserSession) session).MyData = "It's me";
        //...
        //Important: You need to save the session!
        authService.SaveSession(session, SessionExpiry);
    }
}

public class CustomUserSession : AuthUserSession
{

    public string MyData { get; set; }
}

在APPHOST

     using System.Web;
     using ServiceStack;     // v.3.9.60  httpExtensions methods, before in ServiceStack.WebHost.Endpoints.Extensions;

     using ....

AppHost.Configure

AppHost.Configure

     public override void Configure(Container container)
      {
          SetConfig(new ServiceStack.WebHost.Endpoints.EndpointHostConfig
          {
               DefaultContentType = ContentType.Json 
                 ..
               //   remove GlobalResponseHeaders  because CordFeature adds the CORS headers to  Config.GlobalResponseHeaders

            }); 
       Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization")); //Registers global CORS Headers
        this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
        {
            if (httpReq.HttpMethod == "OPTIONS")
                  httpRes.EndRequestWithNoContent();   // v 3.9.60 httpExtensions method before httpRes.EndServiceStackRequest();  

        });

          //Register all Authentication methods you want to enable for this web app.
            Plugins.Add(new AuthFeature(() => new  CustomUserSession(), // OR the AuthUserSession 
                new IAuthProvider[] {
                new  myAuthProvider(),   
              }) { HtmlRedirect = null }); //  Redirect on fail 

HtmlRedirect回答

             Routes.Add<TestRequest>("/TestAPI/{Id}", "POST,GET, OPTIONS");
        ....
      } 

在服务

           [Authenticate]
          public class TestAPI : Service
            {    
                 ...
            }

在JavaScript

in javascript

     jQuery.support.cors = true;

       function make_base_auth(user, password) {
          var tok = user + ':' + password;
          var hash = btoa(tok);
          return "Basic " + hash;
      }

首先登录

           function Authenticate() {

              $.ajax({
              type: 'Post',
              contentType: 'application/json',
              url: serverIP + 'Auth',
              cache: false,
              async: false,
              data: {},
              dataType: "json",
              beforeSend: function (xhr) {
                  xhr.setRequestHeader("Authorization", make_base_auth(username, password));
              },
              success: function (response, status, xhr) {
                  localStorage.sessionId = data.SessionId;
                  var UserName  = response.userName;
              },
              error: function (xhr, err) {
                  alert(err);
              }
          });
      }  

和要求

         function DoTest() {
              var TestRequest = new Object();
              TestRequest.name = "Harry Potter";             
              TestRequest.Id = 33;
             var username = "admin";
             var password = "test"; 

             $.ajax({
              type: 'Post',
              contentType: 'application/json',
              cache: false,
              async: false,
              url: serverIP + '/TestAPI/'+ TestRequest.Id,
              data: JSON.stringify(TestRequest),
              dataType: "json",                  
              beforeSend: function (xhr) {                    
                xhr.setRequestHeader("Session-Id", localStorage.sessionId);
              },
           success: function (response, status, xhr) {
                  var s= response.message;      
              },
              error: function (xhr, err) {
                  alert(xhr.statusText);
              }
          });
      }

这些问题的here和here是有益的。

these questions here and here are helpful.

另外这款回答以CredentialsAuthProvider,如果我们可以用饼干和的访问。

Also this answer for CredentialsAuthProvider, in case we can use cookies and sessions.

 
精彩推荐
图片推荐