2009-12-17 13 views
12

나는 각각 홈, 주제, 게시 됨, 로그인 및 사용자 목록 페이지를 나타내는 일련의 Servlets으로 간단한 포럼을 만들고 있습니다. 이 페이지 중 일부에는 사용자가 로그인하지 않은 상태에서 나타나는 링크가 있습니다.로그인 후 페이지로 리디렉션

내가 원하는 것은 로그인 후 리다이렉션 (RequestDispatcher에서 forward() 사용)을 트리거하는 것입니다. 브라우저는 사용자가 로그인 링크를 클릭하기 전의 페이지로 돌아갑니다. 이를 위해 두 가지 해결책이 있습니다.

첫 번째 해결 방법은 Parameter으로 리디렉션 할 페이지를 나타내는 정보가 포함 된 로그인 버튼과 보이지 않는 필드가있는 Form의 HTML을 사용하는 것입니다. 이것은 가능하지만 다른 것을 시도하고 싶습니다.

두 번째 해결 방법은 어떤 식 으로든 첫 번째 "페이지"를 나타내는 sessionAttribute을 추가하는 것입니다. 이것은 문자열을 포함 할 수 있지만 이것은 첫 번째 접근법과 다르지 않습니다. 또 다른 트위스트는 HttpServlet에 대한 참조를 추가하고 instanceof 또는 정적 인 String 변수를 사용하여 Servlet을 어떤 식 으로든 식별 할 수 있습니다. 그러나이 경우 모든 Servlets에 대해 공통 조상 클래스를 만들어야합니다.

아마 좋은 타협을 형성 할 수있는 또 다른 간단한 해결책이 있을까요? 아니면 위의 솔루션 중 하나가 완벽하게 수용 할 수 있습니까?

답변

24

두 번째 해결 방법보다 먼저 선호합니다. 이것은 요청 범위 정보이고 실제로 세션에 속하지 않으며, 단지 "wtf"로 이어질 것입니다. 동일한 세션에서 여러 개의 창/탭을 열어 본 경험로그인 페이지로 링크를

, 그냥 요청 매개 변수로 현재 URL을 전달합니다

<input type="hidden" name="from" value="${pageContext.request.requestURI}"> 

로그인에서 :

<a href="/login?from=${pageContext.request.requestURI}">Login</a> 

아니면 로그인 페이지에 POST 양식 인 경우 양식을 숨겨진 변수로 다음 요청으로 전송하십시오.

<input type="hidden" name="from" value="${param.from}"> 

로그인 서블릿에서이를 사용하십시오 :

User user = userDAO.find(username, password); 
if (user != null) { 
    request.getSession().setAttribute("user", user); 
    response.sendRedirect(request.getParameter("from")); 
} else { 
    // Show error. 
} 

매우 간단하지 않습니까? :)

일부는 로그인하기 전에 request.getRequestURI() 대신에 로그인 폼 안에 request.getHeader("referer")을 사용하도록 제안 할 수 있습니다. 그러나 이것은 클라이언트가 제어하고 항상 신뢰할 수있는 정보를 반환하지는 않습니다. . 일부 클라이언트는이 소프트웨어를 비활성화했거나 잘못된 값으로 스푸핑하는 일부 소프트웨어 (예 : 기침)를 사용하고 있습니다.

+0

훌륭한 답변입니다. 또한 DAO가 추가되면 무엇을 목표로해야하는지에 대한 스냅 샷을 제공합니다. –

+0

컨테이너 관리 보안을 사용하는 경우 j_security_check에 요청을 게시하면이 작업을 수행 할 수 없습니다. 대신 서블릿 버전 3 프로그래밍 방식의 로그인을 사용하십시오 : HttpServletRequest.login – Ryan

+0

대단히 감사합니다. –

3

페이지에서이 작업을 수행하려는 경우 로그인 페이지는 요청을로드 한 사용자 (request.getHeader("referer"))의 리퍼러 (sic) 헤더를보고 사이트의 페이지인지 확인할 수 있습니다 (그렇지 않은 경우). 헤더가 없습니다 - 어떤 종류의 기본값 사용). 그런 다음 해당 URL을 저장할 것입니다 (로그인 양식에서 숨겨진 필드를 사용 하겠지만 세션 var도 작동합니다). 로그인이 완료되면 저장된 URL로 리디렉션하십시오.

요즘은 대화 상자를 페이지에 오버레이하고 Ajax를 통해 로그인하여 로그인을 할 수 없다면 모든 것을 폴백 메커니즘으로 사용할 수 있습니다. 따라서 페이지를 전혀 떠나지 마십시오. . Bozho가 지적으로


편집 또는 더 나은 아직, 로그인 페이지로 링크로 대상 페이지를 인코딩합니다. 이 아니지만이 아니고 IE가 "referer"헤더를 설정하지 않았을 때 (referer는 필요하지 않음) referer가 필요하지 않으며 비활성화 될 수 있으며 이미 로그인 양식에 링크 된 페이지를 동적으로 생성하고 있기 때문에 왜 취약할까요? 네가 그렇게 할 필요가 없다면. http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.pdf

장 :에서

+1

referer는 필요하지 않으며 IE는 설정하지 않습니다. 따라서 기본 페이지로 리디렉션하는 것이 바람직하지 않습니다. – Bozho

+0

IE8이 Firefox와 동일한 referer 값을 반환하는 것으로 보입니다. 귀하의 회신에서 다른 버전의 IE에는 해당되지 않는다고 생각합니다. –

+1

@ 보소 : 당신이 말하는 것을 (어, 그랬듯이) 확실하지 않습니다. 그냥 그것을 테스트 : IE6 그것을 설정, IE7 그것을 설정, IE8 그것을 설정합니다. –

1

인증이 성공하면 인증 성공의 응용 프로그램 흐름 및 실패

... 는 결과 Authentication 객체는 SecurityContextHolder에 위치 할 것이다. 그런 다음 구성된 AuthenticationSuccessHandler를 호출하여 사용자를 적절한 대상으로 리디렉션하거나 전달합니다. 기본적으로 SavedRequestAwareAuthenticationSuccessHandler가 사용됩니다. 즉, 사용자가 로그인을 요청하기 전에 요청한 원래 대상으로 리디렉션됩니다. ...

+0

감사합니다. Nils. 나는 스프링을 실험 해 왔기 때문에 나중에 유용 할 것이다. –

1

양식의 숨겨진 필드를 사용하는 것은 꽤 표준입니다. 왜 바퀴를 재발 명하려고합니까?

+0

예, HTML을 사용한 표준 사례이지만 웹 애플리케이션의 경우에는 그렇게 확신 할 수 없습니다. 또한 휠을 재발견하는 한 가지 이유는 휠이 필요한 이유를 더 잘 이해하는 것입니다.) –

4

첫 번째 제안 된 접근 방식이 가장 좋습니다. value=request.getRequestURI()으로 숨겨진 필드를 가져 와서 로그인 후 해당 URI로 리디렉션하십시오.

IE (적어도 일부 버전)가 referer 헤더를 설정하지 않았으므로 을 사용하면 작동하지 않습니다.

사용자가 여러 탭을 열면 세션에서 매개 변수를 저장하면 이상한 동작이 발생합니다.

편집 :

some resource -> (requests protected resource) -> (gets forwarded to the login page) -> (should be redirected to the original resource)

대부분의 답변은 "로그인"링크/버튼을 클릭 한 다음 로그인 페이지가 열려 있다고 가정 : 더 나은 질문을 설명하기 위해. 이것은 이야기의 한 면일뿐입니다. 이 경우 원본 리소스 URL을 매개 변수로 추가하여 로그인 양식 (숨겨진 필드에 있음)에 배치 할 수 있습니다.

보호 된 리소스에서 로그인 페이지로을 전달하는 경우 숨겨진 필드에 즉시 요청 URL이 포함되어야합니다.

물론 이것은 문제의 원인이 아니지만 궁극적으로 상황으로 발생하며 고려해야합니다.

+0

음, * 버전 *은 무엇입니까? 참고? IE6, IE7 및 IE8을 테스트했습니다. 그들은 모두한다. (로그인 페이지의 URL로 링크를 인코딩하는 것이 더 좋지는 않을 것입니다.) –

+0

단지 백 링크를 인코딩하기위한 형식을 갖는 것이 잔인한 것으로 보입니다. 로그인 폼 링크로 쿼리 매개 변수로 인코딩하면됩니다. –

+0

대부분의 클라이언트는 referer 헤더를 설정하지만 물론 클라이언트 측에서는 비워두기 위해 설정할 수 있습니다. 그래서 나는 확실히 갈 것입니다. request.getRequestURI() Ben

0

좋아, 여기에 내가 한 일이있다. 로그인은 양식을 보여주는 하나의 서블릿과 사용자 이름 + 비밀번호 조합이 올바른지 여부를 제어하는 ​​두 단계 프로세스입니다. 이 둘은 결합 될 수 있습니다.

매개 변수는 (JSP 아직 추가되어 있지 않은) 형태를 통해 또는 링크를 통해 전송 될 수있다 :

out.println("Login <a href='LoginServlet?comeback=home'>here</a><br>"); 

파라미터는 다음 검색된 다음과 같이

String comeback = request.getParameter("comeback"); 

일단 로그인 정보가 확인되면 다음과 같이 리디렉션을 수행 할 수 있습니다.

RequestDispatcher rd = request.getRequestDispatcher(redirectionPath); 

if(rd != null) 
    rd.forward(request, response); 
관련 문제