簡體   English   中英

ASP.Net MVC自定義身份驗證

[英]ASP.Net MVC Custom Authentication

我有一個Asp.Net MVC webapplication坐在一個仍然主要由delphi管理的網站中。 安全性目前由delphi管理,它創建cookie。

已經決定通過提取cookie詳細信息並將它們傳遞給導入的Delphi DLL來驗證ASP.Net應用程序中的用戶,該DLL根據用戶是否有效返回true或false。

我的計划是使用Forms身份驗證,但不是將用戶重定向到表單而是調用delphi包裝器,如果成功,則將用戶重定向到原始URL。 這樣做的好處是,當安全性遷移到.Net時,身份驗證框架已經存在,只需要實現更改即可。

public ActionResult LogOn(SecurityCookies model, string returnUrl)
    {
        try
        {
            if (model != null)
            {
                Log.DebugFormat("User login: Id:{0}, Key:{1}", model.UserId, model.Key);
                if (authenticator.UserValid(model.UserId, model.Key, 0))
                {
                    FormsService.SignIn(model.UserId, false);
                    return Redirect(returnUrl);
                }
            }
...

請注意,SecurityCookies是由delphi生成的cookie中的自定義綁定類生成的 - 這很有效。

對delphi dll的調用也可以。

我必須克服的問題是幾乎所有對.Net應用程序的調用都是ajax請求。 但是,當用戶未登錄時,瀏覽器會因重定向而進行3次調用:1)原始ajax請求2)重定向到〜/ Account / Logon(上面的代碼)3)重定向回原來的ajax請求

雖然跟蹤回發給客戶端的響應,但顯示步驟3返回正確的數據,整個過程因尚未確定的原因而失敗。 只需單擊客戶端上的刷新即可,因為現在用戶已通過身份驗證,並且不會重定向到〜/ account / Logon。

注意我的客戶端jQuery代碼如下:$ .getJSON(requestString,function(data){//對數據執行某些操作});

有沒有辦法更改窗體身份驗證過程,以便在用戶未經過身份驗證時,而不是重定向到Url,我可以運行其他一些代碼? 我希望身份驗證已經發生在用戶的瀏覽器中完全不可見。

如果要對請求進行身份驗證,則可以通過定義Application_AuthenticateRequest方法在global.asax.cs中執行此操作。 在這里,您可以使用導入的delphi dll讀出自定義cookie並設置Context.User。 asp.net中的所有授權都基於HttpContext中設置的用戶。 Application_AuthenticateRequest方法的實現示例:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    if(authCookie != null)
    {
        //Extract the forms authentication cookie
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        // Create an Identity object
        //CustomIdentity implements System.Web.Security.IIdentity
        CustomIdentity id = GetUserIdentity(authTicket.Name);
        //CustomPrincipal implements System.Web.Security.IPrincipal
        CustomPrincipal newUser = new CustomPrincipal();
        Context.User = newUser;
    }
}

如果cookie無效,那么您將不會在上下文中設置用戶。

然后,您可以創建一個BaseController,如果上下文中提供的用戶經過身份驗證,則所有控制器都將從該檢查繼承。 如果用戶未經過身份驗證,則可以返回HttpUnauthorizedResult。

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (User == null || (User != null && !User.Identity.IsAuthenticated))
        {
           filterContext.Result = new HttpUnauthorizedResult();
        }
        else
        {
            // Call the base
            base.OnActionExecuting(filterContext);
        }
    }
}

在你的web.config中:

<authentication mode="None"/>

因為您不希望將請求重定向到登錄頁面。

我將回答這個具體問題的一部分

有沒有辦法更改窗體身份驗證過程,以便在用戶未經過身份驗證時,而不是重定向到Url,我可以運行其他一些代碼? 我希望身份驗證已經發生在用戶的瀏覽器中完全不可見。

不,那里沒有。 我編寫了一個類似於你的登錄系統,因為它是在表單身份驗證的基礎上構建的,而事實上沒有可擴展性點使它成為一個完整的PITA來編寫。

我能夠覆蓋內置行為的方式是使用HttpModule監視重定向到表單auth URL,然后攔截該操作並讓我處理它。

internal static bool IsFormsAuthenticationLogin(HttpResponseBase response)
{
    if (!response.IsRequestBeingRedirected) return false;
    if (string.IsNullOrWhiteSpace(response.RedirectLocation)) return false;

    Uri formsAuthUri;
    try
    {
        formsAuthUri = new Uri(FormsAuthentication.LoginUrl);
    }
    catch (Exception ex)
    {
        throw new XifCriticalException("Could not construct formsAuthUri", ex);
    }


    Uri redirctUri;
    try
    {
        redirctUri = new Uri(response.RedirectLocation, UriKind.RelativeOrAbsolute);
    }
    catch (Exception ex)
    {
        throw new XifCriticalException("Could not construct redirctUri", ex);
    }

    try
    {
        //Check if the request was redirected by Forms Auth
        bool isFormsAuthenticationLogin = redirctUri.IsAbsoluteUri &&
                                            redirctUri.Host == formsAuthUri.Host
                                            && redirctUri.PathAndQuery.Contains(formsAuthUri.PathAndQuery); 

        return isFormsAuthenticationLogin;
    }
    catch (Exception ex)
    {
        throw new XifCriticalException("Could not construct isFormsAuthenticationLogin", ex);
    }
}

另外需要注意的是,為了能夠在MVC3中依賴此代碼,您可能還需要指定應用程序設置

 <add key="enableSimpleMembership" value="false" />
 <add key="autoFormsAuthentication" value="false" />

幾件事。

首先,因為你顯然是在控制器動作中,所以你應該更換

Server.Transfer(returnUrl, true);

return Redirect(returnUrl);

其次,我通常更喜歡使用ajax調用來進行身份驗證。 用戶應明確地從未經身份驗證的狀態轉移到經過身份驗證的狀態。

第三,如果你必須在通常進行重定向的地方進行ajax調用,你可以做兩件事之一。 在您的控制器中,您可以通過調用擴展方法IsAjaxRequest()來確定它是一個ajax請求(如果是,則返回true)並且如果它是ajax請求則分支不同的結果。 其次,如果你返回一個Redirect,那么它將向客戶端返回一個HTTP重定向,Ajax客戶端代碼應該能夠讀取並響應(例如,通過讀取Location然后對其進行ajax獲取)。 同樣,我不推薦這門課程,但這是可能的。

最后,作為一個完整的左轉...您是否考慮過單獨使用表單auth而不是使用自定義MembershipProvider? 您可以使用它來通過Delphi驗證成員資格,然后使用普通的FormsAuth對象設置客戶端cookie,就像它們在MVC中的示例AccountController中一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM