source

AJAX 및 양식인증, 양식을 방지하는 방법인증이 HTTP 401을 재정의합니까?

manysource 2023. 10. 2. 15:06

AJAX 및 양식인증, 양식을 방지하는 방법인증이 HTTP 401을 재정의합니까?

양식으로 구성된 하나의 응용프로그램에서인증, 인증 쿠키가 없거나 오래된 쿠키를 사용하여 보호된 페이지에 접근할 때, ASP.NET는 HTTP 401 Unauthorized를 발행한 다음 Forms를 발행합니다.인증 모듈은 요청이 끝나기 전에 이 응답을 가로채고 HTTP 302 Found용으로 변경하여 사용자 에이전트를 로그인 페이지로 리디렉션하기 위해 HTTP 헤더 "Location: /path/loginurl"을 설정한 다음 브라우저가 해당 페이지로 이동하여 보호되지 않은 로그인 페이지를 검색하여 HTTP 200 OK를 얻습니다.

AJAX가 고려되지 않았을 때, 그것은 정말로 매우 좋은 생각이었습니다.

이제 애플리케이션에 JSON 데이터를 반환하는 URL이 있으며 사용자 인증이 필요합니다.모든 것이 잘 작동합니다. 문제는 인증 쿠키가 만료되면 내 클라이언트 측 코드가 서버를 호출할 때 로그인 페이지의 html이 있는 HTTP 200 OK를 얻지만 HTTP 401 Unauthorized(이전에 설명되었기 때문에)가 되지 않는다는 것입니다.그럼 제 클라이언트 측에서 로그인 페이지 html을 json으로 파싱하려고 하는데 실패합니다.

그렇다면 문제는: 클라이언트 측의 만료된 인증에 어떻게 대처할 것인가 하는 것입니다.이 상황에 대처하기 위한 가장 우아한 해결책은 무엇입니까?통화 성공 여부를 알아야 하는데 HTTP 시맨틱을 사용하고 싶습니다.

클라이언트 측에서 사용자 지정 HTTP 헤더를 안전한 교차 브라우저 방식으로 읽을 수 있습니까?양식을 알려줄 방법이 있습니까?요청이 AJAX 요청인 경우 리디렉션을 수행하지 않는 AuthenticationModule?HTTP 요청 방법을 재정의할 수 있는 것과 동일하게 HTTP 헤더를 사용하여 HTTP 상태를 재정의하는 방법이 있습니까?

양식 인증이 필요하고, 해당 모듈을 다시 쓰거나 양식 인증 모듈을 직접 작성하는 것을 피하고 싶습니다.

안부 전해요.

저도 같은 문제가 있었고, MVC에서 custom 속성을 사용해야 했습니다.웹 형태로 쉽게 작업할 수 있습니다. 모든 페이지가 일부 기본 페이지에서 상속되는 경우 기본 페이지의 페이지 권한 부여를 재정의할 수 있습니다(MVC의 글로벌 속성은 동일한 것을 허용함 - 응용 프로그램의 모든 컨트롤러/작업에 대해 OnAuthorization 메서드를 재정의함).

속성은 다음과 같습니다.

public class AjaxAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest()
                && !filterContext.HttpContext.User.Identity.IsAuthenticated
                && (filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true).Count() > 0
                || filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true).Count() > 0))
            {
                filterContext.HttpContext.SkipAuthorization = true;
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                filterContext.Result = new HttpUnauthorizedResult("Unauthorized");
                filterContext.Result.ExecuteResult(filterContext.Controller.ControllerContext);
                filterContext.HttpContext.Response.End();
            }
        }
    }

HttpContext를 호출해야 합니다.대답.종료(); 또는 요청이 로그인으로 리디렉션됩니다(이로 인해 머리카락이 일부 빠졌습니다).

클라이언트 측에서는 jQuery ajaxError 메서드를 사용했습니다.

var lastAjaxCall = { settings: null, jqXHR: null };
var loginUrl = "yourloginurl";

//...
//...

$(document).ready(function(){
    $(document).ajaxError(function (event, jqxhr, settings) {
            if (jqxhr.status == 401) {
                if (loginUrl) {
                    $("body").prepend("<div class='loginoverlay'><div class='full'></div><div class='iframe'><iframe id='login' src='" + loginUrl + "'></iframe></div></div>");
                    $("div.loginoverlay").show();
                    lastAjaxCall.jqXHR = jqxhr;
                    lastAjaxCall.settings = settings;
                }
            }
    }

}

현재 페이지의 iframe에서 로그인(사용자가 리디렉션된 것처럼 보이지만 다르게 만들 수 있음)이 표시되었으며, 로그인이 성공하면 이 팝업이 닫히고 원래의 axis 요청이 재전송됩니다.

if (lastAjaxCall.settings) {
        $.ajax(lastAjaxCall.settings);
        lastAjaxCall.settings = null;
    }

이를 통해 사용자는 마지막으로 표시된 형태로 입력한 작업이나 데이터를 잃지 않고 세션이 만료될 때 로그인할 수 있습니다.

이 훔치고 도 있습니다. 하지만 한가지 아이디어는 다음과 같은 것을 구현하는 것일 수도 있습니다.HttpModule로그인 페이지(해당 링크의 instruction)로 리디렉션을 차단합니다.

또한 요청이 AJAX를 통해 이루어지지 않았을 때 기본 동작이 올바른 경우 AJAX를 통해 요청된 경우에만 리디렉션을 가로채도록 HttpModule 예제를 수정할 수 있습니다.

ASP.net , ajax 호출 탐지

그래서 다음과 같은 것들이 있습니다.

class AuthRedirectHandler : IHttpModule
{
    #region IHttpModule Members

    public void Dispose()
    {

    }

    public void Init(HttpApplication context)
    {
        context.EndRequest+= new EventHandler(context_EndRequest);
    }


    void context_EndRequest(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;
        if (app.Response.StatusCode == 302 
            && app.Request.Headers["X-Requested-With"] == "XMLHttpRequest"
            && context.Response.RedirectLocation.ToUpper().Contains("LOGIN.ASPX"))
        {
            app.Response.ClearHeaders();
            app.Response.ClearContent();
            app.Response.StatusCode = 401;
        }
    }

    #endregion
}

앱에 다른 합법적인 302개의 리디렉션이 있는 경우 실제 로그인 페이지로 리디렉션되도록 할 수도 있습니다.

그런 다음 web.config에 추가하면 됩니다.

  <httpModules>
    <add name="AuthRedirectHandler" type="SomeNameSpace.AuthRedirectHandler, SomeNameSpace" />
  </httpModules>

어쨌든. 다시 말하지만, 실제 독창적인 생각이 이 대답에 들어갔습니다. 저는 SO와 웹의 다른 부분에서 다양한 비트를 끌어 모으고 있을 뿐입니다.

수용된 답변을 이행하는 데 문제가 있었습니다.주로, 내 에러 로그는Server cannot set status after HTTP headers have been sent실수.

HTTP 헤더가 IIS 7.5로 전송된 서버가 상태를 설정할 수 없다는 질문에 대해 수락된 답변을 구현하려고 했지만 역시 성공하지 못했습니다.

구글 검색을 좀 해보니 우연히 발견된 것입니다.SuppressFormsAuthenticationRedirect

만약 당신의.은 > 버전 > 4.5 이며, 에 할 수 .HandleUnauthorizedRequest 정의 dAuthorizeAttribute급.

public sealed class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
            base.HandleUnauthorizedRequest(filterContext);
            return;
        }

        base.HandleUnauthorizedRequest(filterContext);
        return;
    }
}

은 입니다.if단을 입니다. 이것은 당신이 켜져 있을 때 가장 간단하게 할 수 있는 일입니다.Net 4.5 및 이미 사용자 지정 권한이 있습니다.

언급URL : https://stackoverflow.com/questions/7532261/ajax-and-formsauthentication-how-prevent-formsauthentication-overrides-http-401