2011-01-31 15 views
3

に再度ログインするために必要な/ランダムに認証されていないユーザーたちは、アウトプロセスSQLセッション状態採用し、ASP.NET 3.5 MVC 1.0とユーザーのセッションがあるIIS 7ASP.NET 3.5 MVC1 -

を使用してフォーム認証ログオン時に正しく設定され、期待通りにタイムアウトし、特別なタイムアウトログインページにリダイレクトされます。問題は、一部のユーザー(すべてではない)がログインし、すぐに認証されずにログインする必要があることです(つまり、元の「ログイン」ページにリダイレクトされます)。

私たちのユーザーが断続的に追い出されている理由は誰にも分かりますか?

EDIT:すべてのApplication_AuthenticateRequestイベントにログを追加してから、ユーザーが起動する前にAuthチケットが認証され、永続的になり、2日後に有効期限が切れ、要求も認証されます。ログオンページに到着すると、ユーザーはもはや認証されなくなります。

EDIT#2:このWebアプリケーションは、ユーザーが認証されていない親アプリ内のスクリプトやその他のコンテンツを探しているため、ユーザーが認証されていないように見えます。次のようにこれらのスクリプトを含めるために、元の形式は次のとおりです。当社の管理組織のビー玉のページで私たちのスクリプト参照に上記の変更で問題が解決

<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.js") %>" type="text/javascript"></script> 

ANSWER:

<script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script> 

私はそれを修正しました。これは明示的に、現在のアプリのルートフォルダを見るようにアプリに指示します。助けてくれたすべての人にありがとう。私は答えとして複数の印をつけることができたと思います!以下は

は、当社のログインアクションです:

以下
[AcceptVerbs(HttpVerbs.Post)] 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", 
     Justification = "Needs to take same parameter type as Controller.Redirect()")] 
    public virtual ActionResult LogOn(string userName, string password, string returnUrl) 
    { 
     if ((HttpContext.Current.User == null) || (!HttpContext.User.Identity.IsAuthenticated)) 
     { 
      if (!ValidateLogOn(userName, password)) 
      { 
       try 
       { 
       return View(); 
       } 
       catch (Exception ex) 
       { 
       throw new Exception(string.Format("User validation failed at LogOn: {0}", ex.ToString())); 
       } 
      } 
     } 

     bool rememberMe = true; 

     FormsAuth.SignIn(userName, rememberMe); 

     Session["userName"] = userName; 

     if (!String.IsNullOrEmpty(returnUrl)) 
     { 
      try 
      { 
       return Redirect(returnUrl); 
      } 
      catch (Exception ex) 
      { 
       throw new Exception(string.Format("User redirect to returnUrl ({0}) failed: {1}", returnUrl, ex.ToString())); 
      } 
     } 
     else 
     { 
      try 
      { 
       return RedirectToAction("Index", "RodWebUI"); 
      } 
      catch (Exception ex) 
      { 
       throw new Exception(string.Format("User redirect to action: Index, controller: RodWebUi failed: {0}", ex.ToString())); 
      } 
     } 
    } 

が私たちのtimeoutlogonアクションです:

public virtual ActionResult TimeOutLogon() 
    { 
     try 
     { 
      FormsAuth.SignOut(); 

      ViewData["TimeoutMsg"] = "Session timed out. Please log back in."; 

      return View(); 
     } 
     catch (Exception ex) 
     { 
      throw new Exception(string.Format("Error with redirecting to TimeOutLogon: {0}", ex.ToString())); 
     } 
    } 

私は以来の現在の状態を記録するために私たちのGlobal.asaxに以下のチェックを追加しましたリクエストと認証チケット。 LogOnに戻す前にすべてが認証され、OKです。

protected void Application_AuthenticateRequest(object sender, EventArgs e) 
    { 
     if (HttpContext.Current.User != null) 
     { 
      if (HttpContext.Current.User.Identity.IsAuthenticated) 
      { 
       if (HttpContext.Current.User.Identity is FormsIdentity) 
       { 
        FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity; 

        FormsAuthenticationTicket ticket = identity.Ticket; 

        LogFunctionCall(HttpContext.Current.User.Identity.Name, "", "User Authentication Check", "", 
             string.Format("Auth ticket is expired: {0}, expiration date: {1}, is persistent: {2}, issued: {3}", 
             ticket.Expired, ticket.Expiration, ticket.IsPersistent, ticket.IssueDate), "", 0); 

        LogFunctionCall(HttpContext.Current.User.Identity.Name, "", "User Authentication Check Line #2", "", 
             string.Format("Raw URL: {0}, Request is authenticated: {1}", HttpContext.Current.Request.RawUrl, HttpContext.Current.Request.IsAuthenticated), "", 0); 
       } 
      } 
     } 
    } 

答えて

2

ロードバランシングウェブサイトはありますか?

もしそうなら、すべてのノードでmachineKeysが同じですか? Forms Cookieの名前は同じですか?これらの値に矛盾がある場合は、1つのノードにログインし、他のノードに対して認証されていないように見えます。

+0

このサイトは単一のサーバー上にあります。 – alan

+0

問題を引き起こしているのはCSS/Imageファイルですか?これらのファイルが別のコンテンツフォルダにある場合、匿名アクセスにする必要があるかもしれません。ページが依存するリソースの要求が問題の可能性があります。 – Ciaran

+0

@Ciaran:これはどういうことか分かりません。これは特定の時間や特定のページには発生しません。ユーザーは自分のホームページを訪問し、別のページに移動し、ログオンページに移動したホームページを更新すると、 – alan

1

これは愚かなことかもしれないが、にreturnurlは、ログインページを指してだろうか?

ユーザーが既にログインしているときにログインページはどのように動作しますか?

+0

いいえ、returnUrlはログインページを指していません。ユーザーはログインし、サイトの別のページに移動すると、リダイレクトされる前に目的のURLを示すreturnUrlを使用してログインページにリダイレクトされます。ユーザーが既にログインしていて、アドレスバーにURLを入力してログインページに移動すると、パスワードが入力されないためログアウトされます。 – alan

+0

@alan:off-topic:この場合、ユーザーはログアウトしません。 「インデックス」への簡単なリダイレクトはより安全です。 – msms

+0

私も同様に、新しい変更を反映するためにログオンアクションコードを更新することに気付きました。ユーザーを再検証する代わりに、ユーザーが認証されているかどうかを確認します。 – alan

2

ASP.Netは、認証されていない場合、またはアクセスしようとしているリソースを表示する権限がない場合、ユーザーをログインページにリダイレクトします。

+0

これらのページにあるすべてのリソースは、ユーザーがログインする前にアクセスできます(つまり、ユーザーはある時点でページにアクセスし、その後、同じページのみを起動し直す必要があります) – alan

+0

信頼できる方法はありますかこの問題を再現するのか?問題が自分自身に表示されるように特定の要求をしたときに、そのことを確実に知ることができますか?もしそうなら、私はどこかでブレークポイントを設定します(global.asaxのBeginRequestは良い場所になります)。そして、要求を調べて、auth cookieがあるかどうか確認してください。認証クッキーを削除する可能性があります(クライアント側で行うことができます)。 –

+0

残念ながら、問題を再現するための信頼できる方法はありません。これは主に原因を突き止めることが非常に困難な理由です。 – alan

0

Spidey senseは、ASP.NETプロセスまたはアプリケーションプールがリサイクルされていると言います。いくつかの理由で起こる可能性があります。セッションは処理中であるため、このイベントではセッションが食べられません。

私はイベントログを見て、何かヒンキーがそこに起こっているかどうか確認したいと思います。

+0

提案していただきありがとうございますが、SQL Session Stateリサイクルを使用してセッションを永続化するように設定したため、ウェブアプリケーションセッションに影響がなくなりました。 – alan

+0

はい、正しいです。しかし、.NETフォーム認証はセッションをまったく使用せず、間違いなくリサイクルによって悪影響を受けます。 –

+0

興味深いですが、マニュアルリサイクルでは、ログインしているすべてのユーザーが再認証を受ける必要がありますか? – alan

1
public partial class MasterPage : System.Web.UI.MasterPage 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
    } 
    protected void signout_Click(object sender, EventArgs e) 
    { 
     Response.Write("<script language=javascript>var wnd=window.open('','newWin','height=1,width=1,left=900,top=700,status=no,toolbar=no,menubar=no,scrollbars=no,maximize=false,resizable=1');</script>"); 
     Response.Write("<script language=javascript>wnd.close();</script>"); 
     Response.Write("<script language=javascript>window.open('login.aspx','_parent',replace=true);</script>"); 
     Session["name"] = null; 
    } 
} 

私はまた、すべてのページにこのコードを追加しています。

protected void Page_Load(object sender, EventArgs e) 
    { 
     Response.Cache.SetCacheability(HttpCacheability.NoCache); 
     Response.Cache.SetAllowResponseInBrowserHistory(false); 
    } 
} 
+0

このスレッドを作成する前にブラウザのキャッシングが無効になっていますが、入力がありがとうございました。また、コードを複製するのではなく、コントローラフィルタを適用することで、これをさらに効率的に達成できます。 – alan