기본 용어

  • 접근 주체 ( Principal ) : 보호중인 대상에 접근하려는 유저
  • 인증 ( Authenticate ) : 해당 유저가 누구인지 검증하는 절차
    • ID, PW 등을 이용한 로그인을 통하여 검증
    • 해당 Application을 이용가능한 유저인가? 에 중점
  • 인가 ( Authorize ) : 인증을 통과한 유저에 대해 권한을 검증하는 절차
    • 인증(로그인)이 이미 되어 있어야 한다.
    • 해당 Service에 대한 권한이 있는가? 에 중점
  • 권한 ( Authorization ) : 인증된 주체가 애플리케이션의 동작을 수행할 수 있도록 허락되있는지를 결정

ex) 네이버 카페에 비교하자면,
네이버 카페라는 Application을 이용할 수 있는 사용자 인가? 즉,
네이버 회원을 검증하는 네이버 로그인 절차가 인증이고,

해당 Application( 네이버 카페 )에서 게시판등의 서비스를 이용할 때
비회원, 준회원, 정회원, 카페 관리자에 대한 권한을 검사하는 절차가 인가이다.


Security 셋팅겸 기본 동작원리 이해

pom.xml ( 의존성 추가 )

Spring Security의 Spring 의존성에 대한 적절한 버전을 확인하고 싶다면 아래의 링크에서
https://mvnrepository.com/artifact/org.springframework.security/spring-security-core
자신의 Security 버전 선택 후 Compile Dependencies의 Version을 확인하세요

    <properties>
        <java-version>1.8</java-version>
        <org.springframework-version>4.3.2.RELEASE</org.springframework-version>
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
        <security.version>4.2.3.RELEASE</security.version>
    </properties>
    <dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-core</artifactId> 
      <version>${security.version}</version> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-web</artifactId> 
      <version>${security.version}</version> 
    </dependency> 
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>${security.version}</version> 
    </dependency>
    <dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-taglibs</artifactId> 
      <version>${security.version}</version> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-test</artifactId> 
      <version>${security.version}</version> 
    </dependency>

필터 등록

아래처럼 서블릿 필터로 등록을 해서
request가 오면 앞단에서 가로채어 요청을 Spring Security에 맞게 처리하는 역할을 한다.

web.xml

    <!-- Spring Security Filter -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

filter-name과 url-pattern( /* )은 수정하지 않고 그대로 써야 정상적으로 작동한다.


Security 설정 파일 생성및 등록

webapp/WEB-INF/spring/appServlet/security-context.xml 파일을 생성 한 후 아래처럼 설정하도록 한다.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                                 http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/security
                                 http://www.springframework.org/schema/security/spring-security.xsd">

        <http auto-config="true" use-expressions="false">
              <!-- 모든 url 패턴에 ROLE_USER의 권한을 가지고 있을때만 접근가능 -->
            <intercept-url pattern="/**" access="ROLE_USER" />
        </http>

        <authentication-manager>
            <authentication-provider>
                <user-service>
                      <!-- 인메모리 방식으로 유저 등록 -->
                    <user name="user" password="userPw" authorities="ROLE_USER"/>
                    <user name="guest" password="guest" authorities="ROLE_GUEST"/>
                </user-service>
            </authentication-provider>
        </authentication-manager>

</beans:beans>

web.xml에 기본코드를 아래처럼 수정한다. ( Security 컨텍스트 설정파일 등록 )

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/root-context.xml
            /WEB-INF/spring/appServlet/security-context.xml
        </param-value>
    </context-param>

결과

현재, 컨트롤러및 뷰는 수정을 하지 않은 상태이다. 이상태에서 서버를 실행시키면?

현재 모든 url pattern( /** ) 은

<intercept-url pattern="/**" access="ROLE_USER" /> 에 의해

ROLE_USER일 경우에만 접근 가능하므로,
기본 url로 접근시 인가를 확인하기위해 먼저 인증절차 페이지 즉,
로그인페이지를 보여준다.
( 자동으로 /login 으로 넘어가며, Spring Security 기본 로그인창을 보여준다. )
8.png


여기서 만약 ID, PW가 틀리다면? ( 인증 절차 통과하지 못한 경우 )
10.png


ID, PW는 맞으나 ROLE_USER의 권한을 가지지 못한 ROLE_GUEST가 로그인한경우 ( 인가를 통과하지 못한 경우 )
9.png


인증에 통과하고 ROLE_USER의 권한을 가지고 있는 경우 ( 인증, 인가 둘다 통과 )
( 원래의 기본 페이지가 나온다. )
11.png

위에서나온 로그인페이지, 로그인실패메세지, 권한없음 등의 페이지는 모두 커스터마이징이 가능하다.


그리고, 위의 스프링 기본페이지에서 인코딩이 깨진듯이 보이는데,

기존에 web.xml에서 하던 UTF-8 인코딩 필터의 경우
아래처럼 springSecurityFilterChain의 위에 위치해야 정상동작한다.

    <!-- UTF-8 Encoding -->
    <filter> 
        <filter-name>encodingFilter</filter-name> 
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
        <init-param> 
               <param-name>encoding</param-name> 
               <param-value>UTF-8</param-value> 
        </init-param> 
        <init-param> 
               <param-name>forceEncoding</param-name> 
               <param-value>true</param-value> 
        </init-param> 
     </filter> 
     <filter-mapping> 
        <filter-name>encodingFilter</filter-name> 
        <url-pattern>/*</url-pattern> 
     </filter-mapping>

            <!-- 🔺 -->

    <!-- Spring Security --> 
    <filter> 
        <filter-name>springSecurityFilterChain</filter-name> 
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 

    <filter-mapping> 
        <filter-name>springSecurityFilterChain</filter-name> 
        <url-pattern>/*</url-pattern> 
    </filter-mapping>

12.png

간단한 동작원리를 파악하기 위해 인메모리 방식을 사용해서 user를 직접 저장했지만,
DB 연동 방식도 가능하다.