如何使用jQuery Ajax对ServiceStack进行身份验证

时间:2013-07-16 06:21:22

标签: ajax servicestack

我正在尝试执行以下操作: jQuery部分:

function ajaxLogin() {
    $.ajax({
         url: "auth/credentials",
         type: "POST",
         data: { UserName: $("#form_username").val(), Password: $("#form_pwd").val() },
         success: function (data) {
             $("#login_div").hide();
         },
         error: function (jqXHR,textStatus,errorThrown) {
             $("$login_msg").text(errorThrown);
         }
    });
}

但是,由于某种原因,它总是回到成功函数,数据包含当前html文档的html内容。

我的ServiceStack AuthProvider包含以下TryAuthenticate:

public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        var session = authService.GetSession();
        string error = null;
        try
        {
            var dataSource = authService.TryResolve<RiskViewDataSource>();
            var diModelInstance = dataSource.diModelRootObject;
            string authResult = UserFactory.authenticate(session.Id, userName, password, false);
            if ("OK".Equals(authResult))
            {
                session.IsAuthenticated = true;
                session.UserName = session.DisplayName = userName;
                session.UserAuthId = password;
                UsersManager.generateUsersPolicies();
                UsersManager.loadUserPolicies();
                return true;
            }
            else
            {
                session.IsAuthenticated = false;
                session.UserName = session.DisplayName = null;
                session.UserAuthId = null;
                authService.RemoveSession();
                return false;
            }
        }
        catch (Exception e)
        {
            Log.Error(e.ToString());
            session.IsAuthenticated = false;
            session.UserName = session.DisplayName = null;
            session.UserAuthId = null;
            error = "Could not connect to RiskView database";
        }

        if (error != null)
        {
            throw HttpError.Unauthorized(error);
        }
        else
        {
            return false;
        }
    }

1 个答案:

答案 0 :(得分:1)

好的,经过一天的混乱之后,我想出了一个适合我的解决方案。我必须创建一个新的登录服务请求。我称之为RenewSession。

服务堆栈部分:

[Route("/RenewSession", "POST")]
public class RenewSessionRequest : IReturn<RenewSessionResponse>
{
}

public class RenewSessionResponse : IHasResponseStatus
{
    public RiskViewJsonObject Result { get; set; }
    public ResponseStatus ResponseStatus { get; set; }
}

public class RenewSessionService : Service, IPost<RenewSessionRequest>
{
    public object Post(RenewSessionRequest request)
    {
        string username = this.Request.GetParam("UserName");
        string password = this.Request.GetParam("Password");
        string message = "";

        IAuthProvider authService = AuthService.GetAuthProvider("credentials");
        Boolean success = false;
        try
        {
            var response = authService.Authenticate(this, this.GetSession(), new Auth { UserName = username, Continue = null, Password = password });
            success = true;
        }
        catch (Exception e)
        {
            message = e.ToResponseStatus().Message;
        }

        return new RenewSessionResponse { Result = new Mapping.RiskViewJsonObject("{ \"success\" : " + (success ? "true" : "false") + ", \"message\" : \"" + RiskViewJsonObject.cleanForJSON(message)+ "\" }") };
    }
}

Html和Ajax Part:

1)在页面中添加div以获取登录详细信息(隐藏它以开始)

<div id="login-div" style="position:absolute;display:hidden;left:100;top:100;background-image:url('images/login_bk.png');">
    <p id="login_error_msg"></p>
    <form id="login_form" onsubmit="loginSubmit(); return false;">
        <table>
            <tr>
                <td>Username:<input id="in_un" type="text" name="UserName" autocomplete="off" autocorrect="off" autocapitalize="off"/></td>
            </tr>
            <tr>
                <td>Password:<input id="in_pw" type="password" name="Password" autocomplete="off" autocorrect="off" autocapitalize="off"/></td>
            </tr>
            <tr>
                <td style="text-align: center;">
                    <input id="login_submit" type="submit" class="hand_cursor" value="Login">
                </td>
            </tr>
        </table>
    </form>
</div>

2)我在我的页面上的每个ajax查询中添加了401个检查(401告诉我们会话已经过期)

$.getJSON('/Menus?format=json', function(data) {
    // Do some stuff
}).fail(function (jqxhr,textStatus,error) {
    if (jqxhr.status == 401) {
        loginAgain();
    }
});

3)显示要重新登录的div

function loginAgain(reloadMenu) {
    $("#login-div").show("slow");
}

4)用于登录表单的登录按钮或onsubmit事件的onclick

    function loginSubmit() {
        if ($("#in_un").val().trim() == "" || $("#in_pw").val().trim() == "") {
            $("#login_error_msg").text("Username or Password is still empty.");
            return false;   // Prevent form from submitting
        } else {
            $("#login_submit_btn").attr("disabled","disabled");
            $("#login_error_msg").text("");
            $.ajax({
                url: "/RenewSession?format=json",
                type: "POST",
                data: { UserName: $("#in_un").val(), Password: $("#in_pw").val() },
                success: function (data, textStatus, jqXHR) {
                    $("#login_submit_btn").removeAttr("disabled");
                    if (data.Result.success) {
                        $("#login-div").hide();
                    } else {
                        if (data.Result.message) {
                            $("#login_error_msg").text(data.Result.message);
                        } else {
                            $("#login_error_msg").text(textStatus);
                        }
                        $("#in_pw").focus();
                    }
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    $("#login_submit_btn").removeAttr("disabled");
                    $("#login_error_msg").text("ERROR: "+errorThrown);
                    $("#in_pw").focus();
                }
            });
        }
        return false;   // Stop the form submiting, we're just gonna hide the div
    }