본문 바로가기

WEB_Programming/Struts

로그인 필터 예제 (Redirect 처리)

Simple Authentication Servlet Filter with JSP/Servlet

자바에서 Servlet filters는 authetication, compression, auding, logging, image conversion, 웹 컨텐츠의 국제화등을 중앙에서 관리할 수 있도록 구현해 주는 인터페이스이다. 여기서 보여주는 서블릿 필터의 예제는 어떻게 간단하게 Java 기반의 웹 애플리케이션에서 인증을 수행하는가에 대해서 보여준다. 이것은 고객이 로그인을 수행했는지 여부와, 페이지가 익스파이어 되었는지, 그리고 각 페이지에 대한 퍼미션 정보를 이 컨텐츠를 통해서 다른 웹 페이지에서 수행하지 않도록 해 준다.

디자인 시나리오는 간단하다. HTTP request가 들어왔을때 로그인 하지 않은 사용자는 login page로 보내진다. 반면 인증된 사용자는 요청된 페이지로 이동을 수행하도록 한다. 사용자가 로그인할 때, 서블릿은 /auth를 호출하고, 인증을 관리한다. 그리고 로그인 실패시 다시 로그인 페이지로 이동하게 만든다. 또한 성공한 경우에는 요청한 페이지로 진행할 수 있도록 해 준다.

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    System.out.print("Authentication: Request received ...");
    try {
        boolean authorized = false;
        if (request instanceof HttpServletRequest) {
            HttpSession session = ((HttpServletRequest)request).getSession(false);
            if (session != null) {
                UserToken token = (UserToken) session.getAttribute("userToken");
                String qryStr = ((HttpServletRequest)request).getQueryString();
                if((token != null) || "cLogin".equalsIgnoreCase(qryStr))
                    authorized = true;
           }
       }

       if (authorized) {
           chain.doFilter(request, response);
       } else if (filterConfig != null) {
           ServletContext context = filterConfig.getServletContext();
           String login_page = context.getInitParameter("login_page");
           System.out.print("Authentication: Login page = " + login_page);
           if (login_page != null && !"".equals(login_page)) {
               context.getRequestDispatcher(login_page).forward(request, response);
           }
      } else {
          throw new ServletException ("Unauthorized access, unable to forward to login page");
      }
    } catch (IOException io) {
        System.out.println("IOException raised in AuthenticationFilter");
    } catch (ServletException se) {
        System.out.println("ServletException raised in AuthenticationFilter");
    }
    System.out.print("Authentication: Response dispatched ...");
}

  • user token은 세션에 들어가있고, 이것은 서블릿에서 인증이 성공된 이후에 값이 세팅되게 된다. 이것은 사용자가 로그아웃 하거나 세션이 expire된 경우에는 자동으로 제거된다.
  • 로그인 페이지는 인증용 쿼리의 인증을 위해서 인증 페이지를 호출한다. 이 예제에서는 login.jsp의 폼은 아마도 "http://domain/servlet/auth?cLogin"이 될 것이다. 아래를 보면 알 수 있다.
  • 우리는 첫번째로 토큰을 검사하고, 이것이 적법한경우 우리는 쿼리 스트링을 확인하지 않는다. 이것은 반복적인 콜을 하지 않도록 해주는 중요한 기능이다.
  • 인증이 성공하면 세션에서 사용자의 토큰이 존재하는지 검사하게 된다. 그러나 사용자가 로그인하는 경우에는 리퀘스트를 처리하도록 놓아둔다.
  • 만약 인증이 실패하고, 올바른 설정값이 존재한다면 우리는 단순하게 로그인 페이지로 요청을 보내게 된다. 그렇지 않은경우 예외를 던진다. (아마도 절대로 이 상황은 오지 않을것이지만... ^^). 애플리케이션을 위한 기본적인 에러 페이지가 화면에 보일 것이다.
Web.xml
Add to the root <app> node.
<context-param>
<param-name>loginPage</param-name>
<param-value>/login.jsp</param-value>
</context-param>

<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>com.package.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Code snippet for Login Page
<%
String urlParams = url + "/auth?cLogin";
%>
<form action="<%=urlParams%>" method="POST">
// Form components
</form>

Code snippet for Servlet:
- 보는것과 같이 doPost()메소드가 호출되면 이미 요청으로 부터 파라미터를 추출하게 된다. 파라미터가 cLogin이될 것이다.
private void performLogin(HttpServletRequest request, HttpServletResponse response,     String username,
String password, ServletContext context) throws ServletException, IOException {
    if((username!=null) & (password!=null)) {
        User user = userFacade.findByUsername(username);
        if(user!=null) {
            UserToken tok = Authentication.authenticateUser(user, username, password);
            if (tok != null) {
                request.getSession().setAttribute("userToken", tok);
                response.sendRedirect(context.getContextPath());
            }
        } else {
            String url = context.getInitParameter("login_page");
            if (url != null && !"".equals(url)) {
                response.sendRedirect(url);
            }
        }
    } else {
        String url = context.getInitParameter(
"login_page");
        if (url != null && !"".equals(url)) {
            response.sendRedirect(url);
        }
    }
}

이게 다다. 웹 애플리케이션에 이 필터를 디플로이 하면 모든 요청에 대해서 인터셉터를 수행하고, 인증 검사를 수행하게 된다.