0

알 수없는 mvc 5 웹 응용 프로그램에서 이상한 문제가 발생했습니다. 응용 프로그램은 내 조직을 위해 만든 내부 웹 응용 프로그램입니다. 주로 도메인에 연결된 컴퓨터를 사용하는 직원이 액세스하지만 모바일 장치 및 태블릿을 통해 액세스합니다. Windows auth와 AD를 통해 이전의 자동 로그인 경험을 제공하고자했습니다. (도메인에 이미 로그온 한 경우 자격 증명을 입력하지 않고도) 다른 모든 사용자에게 사용자 로그인 화면을 제공 할 수 있기를 원했습니다. 브라우저 기본 프롬프트. 이를 구현하기 위해 저는 Windows 사용자를 인증하고 암호화 된 쿠키를 사용자의 역할이있는 기본 응용 프로그램으로 다시 보내는 별도의 웹 응용 프로그램을 만들었습니다. 비 Windows 기반 브라우저는 AD에 대해 인증하고 사용자의 역할을 검색하는 기본 응용 프로그램의 로그인 페이지로 제공됩니다. 각 로그인 유형에 대해 역할은 클레임으로 변환되지 않고 사용자에 대해 페더레이션 토큰이 만들어집니다. 내 문제는 사용자가 Windows 인증 앱으로 리디렉션을 통해 로그인 할 때 이상한 문제가 발생한다는 것입니다. 표준 양식 제출 또는 AJAX 게시 여부에 관계없이 제출하는 양식은 페이지로드 중 1 분 이내에 제출해야합니다. 그렇지 않으면 컨트롤러 조치에 전송 된 매개 변수가 바인드되지 않습니다 (null). 사용자가 사용자 정의 로그인 페이지를 통해 로그인하면이 문제점이 존재하지 않습니다.ASP.NET MVC 작업 매개 변수가 양식이 유휴 상태 일 때 바인딩되지 않음

 <AllowAnonymous> 
    <HttpPost> 
    <ValidateAntiForgeryToken> 
    <OutputCache(NoStore:=True, Duration:=0, Location:=OutputCacheLocation.None, VaryByParam:="None")> 
    Public Function LogUserIn(model As User, returnURL As String) As ActionResult 

     Try 
      If ModelState.IsValid Then 

       If Membership.ValidateUser(model.UserName, model.PassWord) Then 

        'Call helper function to get all user roles and convert them to claims 
        Dim userClaims As List(Of Claim) = New LDAPHelper().GetUserGroups(model.UserName) 
        userClaims.Add(New Claim(ClaimTypes.WindowsAccountName, model.UserName)) 
        userClaims.Add(New Claim(ClaimTypes.NameIdentifier, model.UserName)) 
        userClaims.Add(New Claim(ClaimTypes.Name, model.UserName)) 
        Dim claimIdent As New ClaimsIdentity(userClaims, "Custom") 

        Dim claimPrinc As New ClaimsPrincipal(claimIdent) 
        Dim token = New SessionSecurityToken(claimPrinc) 
        Dim sam = FederatedAuthentication.SessionAuthenticationModule 
        sam.WriteSessionTokenToCookie(token) 


        If returnURL Is Nothing Then 
         Return Redirect("~/") 
        Else 
         Return Redirect(returnURL) 
        End If 

       Else 
        ModelState.AddModelError("LoginFailure", "The username/password combination was invalid") 

       End If 



      End If 

      Return Nothing 

     Catch ex As Exception 
      ModelState.AddModelError("LoginFailure", ex.Message) 
      Return Nothing 
     End Try 

    End Function 

: 여기

Protected Sub Application_AuthenticateRequest() 

    Dim user As System.Security.Principal.IPrincipal = HttpContext.Current.User 


    If user Is Nothing Then 


     'First check if an authentication cookie is has been generated from the windows login 
     'authentication app 
     Dim authCookie As HttpCookie = Request.Cookies(".ConnectAUTH") 

     If Not authCookie Is Nothing Then 

      ' Extract the roles from the cookie, and assign to our current principal, which is attached to the HttpContext. 
      Dim ticket As FormsAuthenticationTicket = FormsAuthentication.Decrypt(authCookie.Value) 


      Dim claims As New List(Of Claim) 
      For Each role In ticket.UserData.Split(";"c) 
       claims.Add(New Claim(ClaimTypes.Role, role)) 
      Next 


      Dim claimIdent As New ClaimsIdentity(claims, "Custom") 

      claimIdent.AddClaim(New Claim(ClaimTypes.WindowsAccountName, ticket.Name)) 
      claimIdent.AddClaim(New Claim(ClaimTypes.NameIdentifier, ticket.Name)) 
      Dim claimPrinc As New ClaimsPrincipal(claimIdent) 
      Dim token = New SessionSecurityToken(claimPrinc) 
      Dim sam = FederatedAuthentication.SessionAuthenticationModule 
      sam.WriteSessionTokenToCookie(token) 

      HttpContext.Current.User = New ClaimsPrincipal(claimIdent) 


      Return 

     Else 'User hasn't been authenticated 

      Dim ConnectBaseURL = Request.Url.GetLeftPart(UriPartial.Authority) & "/" 
      Dim mvcPath As String = Request.Url.ToString.Replace(ConnectBaseURL, "") 

      'If user is requesting the login page then let them authenticate through there 
      If mvcPath.ToUpper.Contains("ACCOUNT/LOGIN") Or mvcPath.ToUpper.Contains("ACCOUNT/LOGUSERIN") Or mvcPath.ToUpper.Contains("SIGNALR") Then Exit Sub 

      'for brevity i will omit the code below: 
      ' Basically it checks whether the browser is windows based if so then it redirects the user to 
      ' a windows login authenticator which authenticates the user against Active Directory, builds and sends 
      ' an encrypted cookie with a list of roles/groups that the user belongs to. When this function detects that cookie 
      ' it decrypts it, sets up a claims identity, add the user roles and creates a federated authentication token 

      'If the the browser is not windows based then it redirects the user to a custom login page which is tied to an MVC 
      'action that will also authenticate the user against active directory and and set up the claims identity ... 


     End If 
    End If 


End Sub 

그들이 정의 로그인 페이지로 리디렉션 된 경우 사용자를 인증 코드이다 : 여기

는 Global.asax에의 초기 인증을 수행하는 코드 Windows 인증 응용 프로그램에서 보내지 않고 주 앱으로 리디렉션 된 후에 클레임 및 토큰 생성을 하드 코딩하여 방정식에서 폼 쿠키를 제거하려고했습니다. HttpContext.Current.User 객체는 Application_AuthenticateRequest에 도달 할 때마다 유효한 claimPrincipal으로 설정되어 있습니다. 사용자 정의 AuthorizeAttribute를 구현했으며 사용자는 항상 인증되고 권한이 부여됩니다. 재미있는 점은 매개 변수가 null로 전달 된 직후 양식의 제출 단추를 다시 누르면 작동한다는 것입니다. 나는 비슷한 문제에 대해 온라인으로 샅샅이 뒤졌다 - 아무것도 - 나는 여기에있는 누군가가 아이디어를 갖고 있기를 바라고있다.

답변

0

내 대답은 완전히 관련이 없지만 도움을 요청하는 중입니다. 우리에게는 비슷한 것이있었습니다. MVC4의 웹 API에서 MVC5로 전환했을 때. 토큰을 검사하는 AuthorizationAttribute가 있습니다. 우리는 그것을 읽었고, 교장을 설정했지만, 우리가 컨트롤러 액션을 눌렀을 때, 교장은 사라졌습니다 (mVC5에서 - 이것은 이전 버전에서 작동했습니다). 짧은 이야기는 MVC5의 비동기 성질과 관련이 있다는 것이 었습니다. 우리는 IAuthenticationFilter (mVC5가 주체를 설정할 것으로 기대되는 곳)를 구현하는 또 다른 속성을 구현하기 위해 방법을 변경했습니다. 이것은 당신과 어떤 관련이 있습니까? MVC5 이 어떤 경우에 님이 프린시 펄 (Application_AuthenticateRequest 이 아닐 수도 있습니다)을 설정할 것으로 예상되는지 여부를 알아야합니다. 그 밖의 다른 것들은 잘못된 스레드에서 설정 될 수 있으며 컨트롤러에 도착할 때 사라질 수 있습니다.

+1

Willy에게 감사드립니다.하지만 세션 인증 토큰을 사용할 때마다 모든 요청에 ​​대해 교장을 설정할 필요가 없습니다. 사용자가 로그인하고 인증되면 클레임 ID/principal을 사용하여 세션 토큰이 만들어지며 토큰이 유효하지 않거나 로그 아웃 될 때까지 설정 상태를 유지합니다. 컨트롤러 동작을 확인했는지 그리고 사용자 ID가 여전히 설정되어 있지만 작업에 전송 된 매개 변수가 null인지 확인하려면 – PlasmaX