servlet (2)

💻 Programming/JSP

[JSP] Security ( 보안 )

JSP와 servlets 은 Web 개발자들을 위해서 보안(인증)을 처리할 수 있는 다양한 방법을 제공합니다.  

오늘은 그 중 두가지에 대해서만 알아보도록 하겠습니다. 

 

역할 기반 인증

servlet 에서 제공하는 역할 기반 인증은 사용자 레벨에서 리소스를 제한하는 것이 아니라 사용자에게 역할을 부여하고 특정 역할을 가진 모든 사용자에 대해서 리소스를 제한하는 방법입니다.  

톰캣 홈 디렉토리의 conf디렉토리에 tomcat-users.xml 파일을 만들고 아래코드를 넣어주세요.

<?xml version='1.0' encoding='utf-8'?> 
<tomcat-users> 
	<role rolename="tomcat"/> 
	<role rolename="role1"/> 
	<role rolename="manager"/> 
	<role rolename="admin"/> 
	<user username="tomcat" password="tomcat" roles="tomcat"/> 
	<user username="role1" password="tomcat" roles="role1"/> 
	<user username="both" password="tomcat" roles="tomcat,role1"/> 
	<user username="admin" password="secret" roles="admin,manager"/> 
</tomcat-users>

위 코드가 뭘 하고있는지는 대충 봐도 아시겠죠? 역할을 생성하고 사용자를 만들때 역할을 부여하고 있습니다.

 

이제  web.xml파일에 <security-constraint> 태그를 추가하고 아래처럼 넣어보세요. 물론 url-pattern은 여러분이 가지고 있는 웹애플리케이션에 실제로 존재하는 url이어야게죠? 그래야 테스트가 가능합니다~ 

 

<web-app> 
    ... 
    <security-constraint> 
    	<web-resource-collection> 
        	<web-resource-name> SecuredBookSite </web-resource-name> 
            <url-pattern>/secured/*</url-pattern> 
            <http-method>GET</http-method> 
            <http-method>POST</http-method> 
        </web-resource-collection> 
        <auth-constraint> 
        	<description> Let only managers use this app </description> 
            <role-name>manager</role-name> 
        </auth-constraint> 
    </security-constraint> 
    <security-role> 
    	<role-name>manager</role-name> 
    </security-role> 
    <login-config> 
    	<auth-method>BASIC</auth-method> 
    </login-config> 
    ... 
</web-app>

위 소스코드가 의미하는 것이 무언인가 하면 다음과 같습니다. 

  • HTTP GET 이나 POST 방식의 요청에 대해서 /secured/* URL에 대한 요청이 들어오면 보안설정의 제약을 받게됩니다.

  • 매니저 역할을 가지고 있는 사용자에 대해서만 /secured/* 리소스에 접근이 가능합니다.

  • 마지막으로 login-config 태그가 기본형태의 인증을 위해서 사용되었습니다. 

이제 /security내부의 페이지로 접근을 하려면 사용자명과 비밀번호를 입력하라는 창이 뜨게됩니다. 접속할 수 있는 역할을 가지고 있지 않거나 인증에 실패하면 접속이 불가능하나 페이지가 되는 것이죠. 

 

Form을 이용한 인증

FORM 인증을 사용하려면 사용자에게 로그인 폼을 제공해주어야 합니다.  

<html>

<body bgcolor="#ffffff">
    <form method="POST" action="j_security_check">
        <table border="0">
            <tr>
                <td>Login</td>
                <td><input type="text" name="j_username"></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="j_password"></td>
            </tr>
        </table> <input type="submit" value="Login!"> </center>
    </form>
</body>

</html>

위 코드를 login.jsp에 넣어주세요. <form> 태그 안에있는 action의 값은  j_security_check 여야 합니다. POST 방식이 사용되어야 한다는 것은 알고 계시겠죠? 자 이제 web.xml의 <login-config> 태그를 FORM을 이용하도록 수정해야합니다.

<web-app> 
    ... 
    <security-constraint>
        <web-resource-collection>
            <web-resource-name> SecuredBookSite </web-resource-name>
            <url-pattern>/secured/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description> Let only managers use this app </description>
            <role-name>manager</role-name>
        </auth-constraint>
    </security-constraint>
    <security-role>
        <role-name>manager</role-name>
    </security-role>
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config> 
    ...
</web-app>

이제  /secured/* 주소로 접속을 시도해 보세요. 사용자 ID와 패스워드를 입력하라고 할겁니다. 컨테이너가  "j_security_check" 액션을 만나면요청을 인증하기위한 내부 메카니즘을 실행합니다.

로그인이 성공하고 리소스를 조회할 수 있는 역할을 가지고 있다면 컨테이너는 사용자를 확인하기위해서 session-id 를 비교합니다. 컨테이너는 세션아이디를 가지고있는 쿠키와 함께 세션을 유지하게됩니다. 서버가 이 쿠키를 클라이언트로 되돌려보내고 이후 요청때마다 이 쿠키를 서버로 전송하게되면 컨테이너는 요청하는 클라이언트를 식별할 수 있습니다.

로그인이 실패하면 서버는 에러페이지를 전송하게 됩니다.  

 

j_security_check 가 톰캣 컨테이너에서 어떻게 동작하는지에 대해서 더 자세한 정보를 보시려면 Standard Realm Implementations 이곳에 가보세요. 

 

Servlet/JSP의 코드로 보안적용하기

HttpServletRequest 객체가 보안관련해서 제공하는 메소드들은 다음과 같습니다.

 

SN Method and Description
1 String getAuthType()
The getAuthType() method returns a String object that represents the name of the authentication scheme used to protect the Servlet.
2 boolean isUserInRole(java.lang.String role)
The isUserInRole() method returns a boolean value: true if the user is in the given role or false if they are not.
3 String getProtocol()
The getProtocol() method returns a String object representing the protocol that was used to send the request. This value can be checked to determine if a secure protocol was used.
4 boolean isSecure()
The isSecure() method returns a boolean value representing if the request was made using HTTPS. A value of true means it was and the connection is secure. A value of false means the request was not.
5 Principle getUserPrinciple()
The getUserPrinciple() method returns a java.security.Principle object that contains the name of the current authenticated user.

 

예를들어 매니저 권한을 갖고있는 사용자들을 위한 링크를 제공하는 JavaServer Page 를 만들려면 아래 코드를 삽입해주시면 되는거죠 

<% if (request.isUserInRole("manager")) { %> 
    <a href="managers/mgrreport.jsp">Manager Report</a> 
    <a href="managers/personnel.jsp">Personnel Records</a> 
<% } %>

그러면 사용자 역할을 검사한 뒤 매니저역할을 가지고 있는 사용자에게만 링크를 보여주게 됩니다. 만약 로그인 폼에서 입력한 사용자명이 필요한 경우에는 getRemoteUser 메소드를 호출하면 됩니다.

 

 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_security.htm 

 

 

 

 

 

 

💻 Programming/JSP

[JSP] Filters ( 필터 사용하기 )

Servlet과 JSP 필터는 서블릿과 JSP프로그래밍에서 아래와 같은 목적으로 사용될 수 있는 Java 클래스입니다.

  • 클라이언트로부터의 요청이 백엔드로 가기 전에 가로채기 위해서

  • 서버로부터의 응답이 클라이언트로 보내지기 전에 조작하기 위해서

아래는 많이 사용되는 필터들의 종류입니다.

  • Authentication Filters.

  • Data compression Filters

  • Encryption Filters .

  • Filters that trigger resource access events.

  • Image Conversion Filters .

  • Logging and Auditing Filters.

  • MIME-TYPE Chain Filters.

  • Tokenizing Filters .

  • XSL/T Filters That Transform XML Content.

Filter는 deployment descriptor 파일인 web.xml을 통해서 디플로이 되고 servlet 이나 JSP에 매핑이 됩니다. web.xml 파일은 <Tomcat-installation-directory>\conf 디렉토리에서 찾으실 수 있습니다.

JSP 컨테이너가 웹애플리케이션을 시작할 때, 컨테이너는 각 필터의 인스턴스를 생성합니다. 당신이 deployment descriptor에 선언한 필터들을 말이죠. 그 필터들은 정의된 순서대로 실행이 됩니다. 


Servlet Filter Methods:

필터는 간단히 말해서 그냥 Java 클래스입니다.  javax.servlet.Filter 인터페이스를 구현한 클래스라고 할 수 있죠. The javax.servlet.Filter interface 는 아래의 세가지 메소드를 선언하고있습니다.

S.N.Method & Description
1public void doFilter (ServletRequest, ServletResponse, FilterChain)
This method is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.
2public void init(FilterConfig filterConfig)
This method is called by the web container to indicate to a filter that it is being placed into service.
3public void destroy()
This method is called by the web container to indicate to a filter that it is being taken out of service.


JSP Filter 예제

아래는 JSP Filter 예제입니다. 무엇을 하는고 하니, 요청이 들어올 때마다 클라이언트의 IP주소를 프린트하고 현재 시간을 뿌려줍니다. 이 예제를 통해서 JSP Filter의 기본적인 사용법을 익힐 수 있을거에요.  

// Import required java libraries import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.*; // Implements Filter class public class LogFilter implements Filter { public void init(FilterConfig config) throws ServletException{ // Get init parameter String testParam = config.getInitParameter("test-param"); //Print the init parameter System.out.println("Test Param: " + testParam); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException { // Get the IP address of client machine. String ipAddress = request.getRemoteAddr(); // Log the IP address and current timestamp. System.out.println("IP "+ ipAddress + ", Time " + new Date().toString()); // Pass request back down the filter chain chain.doFilter(request,response); } public void destroy( ){ /* Called before the Filter instance is removed from service by the web container*/ } }

이제 LogFilter.java를 컴파일하고 LogFilter.class 파일을 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 디렉토리에 넣어주세요. 그리고 아래에서 매핑시켜주는 작업을 더 해야합니다. 


JSP Filter Mapping in Web.xml:

web.xml 에서 필터를 매핑할 때는 아래처럼 사용하시면 됩니다.

<filter> <filter-name>LogFilter</filter-name> <filter-class>LogFilter</filter-class> <init-param> <param-name>test-param</param-name> <param-value>Initialization Paramter</param-value> </init-param> </filter> <filter-mapping> <filter-name>LogFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

위 소스처럼 매핑하면 모든 서블릿과 JSP에 적용이 됩니다.  url pattern에서 /* 이 의미하는 것이 모든 것이기 때문입니다. 즉, 이곳에 특정 servlet 이나 JSP를 넣어 줄 수도 있다는 말이죠.

이제 JSP페이지를 요청하면 웹서버 로그에서 생성된 로그를 보실 수 있습니다.  Log4J 로거를 사용해서 다른 파일에 로그를 기록할 수도 있다는점도 참고하시기 바랍니다.


Filter 여러개 사용하기

여러개의 필터를 사용해야 한다면 아래처럼 사용하시면 됩니다. 각각의 필터를 정의하고 각각 매핑을 하는거죠. 

<filter> <filter-name>LogFilter</filter-name> <filter-class>LogFilter</filter-class> <init-param> <param-name>test-param</param-name> <param-value>Initialization Paramter</param-value> </init-param> </filter> <filter> <filter-name>AuthenFilter</filter-name> <filter-class>AuthenFilter</filter-class> <init-param> <param-name>test-param</param-name> <param-value>Initialization Paramter</param-value> </init-param> </filter> <filter-mapping> <filter-name>LogFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>AuthenFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

Filters Application Order:

필터의 적용 순서를 바꿀 수도 있습니다. 먼저 정의된 필터가 먼저 적용이 되는거죠. 위 예제에서는 LogFilter가 AuthenFilter보다 우선 적용이 되는거고 아래 예제에서는 AuthenFilter가 LogFilter보다 우선 적용됩니다.

<filter-mapping> <filter-name>AuthenFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>LogFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

 

 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_writing_filters.htm