프로그래밍/해외인턴 개발일지

[인턴 일지] 초기 개발 과정과 스프링 시큐리티 로그인

Jay Tech 2017. 10. 14. 03:30
반응형

개발 과정에 있어서 많은 어려움들이 있었다. 에러 하나 터지면 수습하는데 얼마나 걸릴지 몰라 프로젝트 기간을 확실히 말을 하지 못했다. 원래 프로젝트는 due date을 정해놓고 에러가 터지면 그날 집에 가지 못하는 사이클을 경험했었지만 회사 자체가 야근을 싫어하고 미국에서의 work & life balance를 경험하고 싶었기 때문에 길게 잡았다. 


그래도 재촉하기 떄문에 차분히 정리할 경황이 없었다. 포스팅 또한 정신이 없겠지만 중요하게 생각하는 과정과 에러해결 과정을 나열해 보겠다.


일단 Maven상에서 에러가나서 Package UI상에 빨간 엑스표시가 뜨는 문제이다.





지금은 안나오지만 저 프로젝트 그림 밑에 엑스표시가 나는 경우가 있다. 밑으로 dept를 쭉 펼치면 에러 tracking이 된다. 하위 폴더에 엑스표시가 뜨기 때문이다. 근데 한동안 저 꼭대기에만 뜨고 에러가 tracking이 되지 않았다. 뭔가 단단히 잘못된건가하고 찜찜한 마음을 안고 프로젝트를 키워가고 있는데 도저히 찜찜해서 잠을 못잤다.


근데 매우 간단한 문제였다. 하단에 console창 근처에 Problems탭이 있다. 저기서 말해주는 것을 미처 알아채지 못했다. 보면 Maven Configuration Problem이라고 에러표시가 나와있었다. 그냥 프로젝트 우클릭 후 Maven -> Update Project를 해서 메이븐 업데이트를 해주니 그냥 해결되었다.




그리고 프로젝트 자체에 로그인 기능이 있어야 한다. 각 매장 관리자들에게 아이디를 부여하여 운영하려고 하기 떄문이다. 그런데 회원가입까지는 아직 필요가 없다고 생각했다. 일단 주어진 기간이있고 당장 운영하기에 필요가 없기 때문이었다. 추후 유지 보수 과정에서 기간을 더 받고 추가를 하려고한다. Amazon Cognito 서비스를 이용한 이메일 인증을 통한 매니저들 회원가입을 진행하려고 한다. 최대 admin인 나에게 메일이 와서 내가 confirm하는 형식이다. 아마존 세미나에 참석했을 때 인증 서비스를 같이 구현했었는데 기억이 가물가물하다... 


스프링 시큐리티는 스프링 프레임워크 자체에서 제공하는 인증 방식이다. 인증방식이 까다롭고 힘든 이유는 보안에 대한 지식이 없기 때문이라는 이유, 그리고 괜히 어설프게 만졌다가 피해가 발생했을 때의 책임까지 리스크가 컸다. 그래서 스프링 시큐리티를 이용한다. 나로썬 쉽고 편리할 뿐 아니라 지식이 없는 상태에서 최선의 방어를 할 수 있는 선택이었다. 


하지만 이것 또한 만만치 않다. 시큐리티 목록만 따로 빼서 두꺼운 책이 나올정도니... 매우 crucial한 부분이다. 그리고 essential하다. 인증과 보안이 없다면 사이트는 집에 문을 열어놓고 사는 것과 마찬가지 이기 때문이다. 그리고 회사에서 요구하는 프로젝트안에 개인 정보가 들어있기 때문에 최대한 할 수 있는 만큼 막아 놓아야 한다.


어떻게 권한을 부여할지, 세션유지는 어떻게 해야할지, 로그인 상태에서 중복 로그인을 시도하면 어떻게 처리해야 할지 등등 많은 issue들이 있다. 이걸 혼자 이 기간안에 학교 졸업도 못한 내가 하기에는 자신감만으로는 힘들었다..


간단하게 정리 해 보겠다. 스프링은 가로채는 것을 참 좋아하는 것 같다. 프로젝트 시작부터 dispatcher servlet이 가로채면서 시작하는 것처럼 말이다. 근데 이 가로채는 것이 매우 효율적이고 쓰기 좋은 것 같다. 왜냐하면 일일이 다 지정해주지 않아도 되기 때문이다.


일단 web.xml에 필터를 지정해 준다.


1
2
3
4
5
6
7
8
9
10
<!-- security setting -->
    
    <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>
cs


filter name은 springSecurityFilterChain이다. 이 것은 스프링 시큐리티의 내부 빈으로써 자동으로 생성된다. 이 필터는 dispatcher servlet 보다 우선한다. 즉 같은 url을 타더라도 먼저 가로채 버린다.


보안 관련 context.xml파일을 따로 제작한다.  web.xml에 등록을 해야 발동이 되지만 보는 것과같이 클래스 패스를 이렇게 지정해 주면 해당 폴더 밑에 파일들이 이름만 맞춰주게 되면 자동으로 발동되게 된다.





이제 context-security.xml을 보자.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?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-4.1.xsd
 http://www.springframework.org/schema/security
 http://www.springframework.org/schema/security/spring-security-4.1.xsd">
 
     <http auto-config="true" use-expressions="true">
         <intercept-url pattern="/home.do" access="permitAll"/>
     
         <intercept-url pattern="/login.do" access="permitAll"/>
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
        
        <form-login login-page="/login.do"
                    default-target-url="/home.do"
                    authentication-failure-url="/login.do"
                    username-parameter="id"
                    password-parameter="pw"
        
        /
        <logout logout-url="/logout"
                logout-success-url="/main.do"/>
 
 
        <session-management invalid-session-url="/login.do">
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
        </session-management>
        <csrf/>
    
     </http>
     
    
    <authentication-manager>
 
        <authentication-provider>
                  <user-service>
                     <user name="user" password="user" authorities="ROLE_USER" />
                     <user name="admin" password="admin" authorities="ROLE_ADMIN" />
                     
                  </user-service>
        </authentication-provider>
    </authentication-manager
 
 
</beans:beans>
cs


여기서 에러가 막 터져서 삽질을 엄청하였다. 버젼이 안 맞아서 자꾸 에러가 났던 것이다. 저기 위에 namespace의 버전이 beans와 security가 지금은 4.1로 바꿔놓았다. 저게 실제 maven에 있는 버전과 맞지 않아서 계속 아다리가 안 맞았었다. 위의 코드는 내 프로젝트에 맞게 수정한 것이고 제일 기본 뼈대 만 본다면 



1
2
3
4
5
6
7
8
9
10
11
<http auto-config="true">
    <intercept-url pattern="/-" access="ROLE_USER" />
</http>
 
<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="guest" password="guest" authorities="ROLE_USER"/>    
        </user-service>
    </authentication-provider>
</authentication-manager>
cs



이렇게 될 것이다. 이것만 설정해주고 돌려보기만 해도 신기하게도 로그인 창이 뜬다... 처음에 엄청 혼란 스러웠다. 난 앞단 파일을 건든적이 없는데 왜 로그인 창이 뜨는거지? xml태그만으로 저게 되나? 


저 auto-config=true라는 친구 덕분에 저런 창이 만들어진다. 


다시 윗부분 코드를 본다면


1
2
3
<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/-" access="hasRole('ROLE_USER')"/>
</http>
cs



이런식으로 되어 있는데 이게 예전 버전은 use-expressions 속성을 쓰지 않고 hasRole도 쓰지 않았다. 4이상인가 부터는 저런 식으로 쓰는 것 같다. 

use-expressions를 쓴다는 것은 표현식을 쓴다는 것이다. hasRole, hasAnyRole등 여러 표현식들이 있다. 이건 찾아보면 나온다. 즉 ROLE_USER라는 권한이 있는 사람만 타게 한다는 것이다.



이렇게 기본 뼈대를 만들었다. 앞단 화면이 뜨는 것 까지 신기했지만 그 신기함도 잠시 저렇게 html로만 이루어진 딱딱한 디자인의 화면은 절대로 쓰고 싶지 않을 것이다.  우리는 로그인 페이지를 커스텀 해야한다.


form-login에서 속성들을 준다.


login-page : 이 속성이 내가 로그인 페이지로 하고 싶은 url을 적는 부분이다.

username-parameter, password : 로그인 할때 input필드의 이름을 정하는 것이다. 이게 서로 아다리가 맞아야 제대로 넘어간다.

여러 속성들이 있는데 필요한 것들을 해주면된다. 로그인 실패시 이동할 url, 중복 로그인 시도시 이동할 url 등 여러 속성들이 있다.


1
2
3
<session-management invalid-session-url="/login.do">
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
        </session-management>
cs


이 부분이 중복 로그인 처리 부분이다... 진짜 스프링 너무 고맙다... 가독성이 좋아서 그냥 읽기만 해도 뜻이 이해될 것이다. 세션 최대 1개 두고 저 error-if 태그는 이미 로그인 상태에서 다른사람이 같은 계정으로 로그인 시도시 2번 째 사람이 차단당하는 기능이다. 저게 없으면 먼저 있던 사람이 튕겨져 나갈 것이다.


<csrf/>는 다음에 포스팅을 따로 두고 하려고한다.


그리고 밑에 보면 user들을 하나씩 built in으로 넣고 있는데 이러면 원래 안되고 DB를 거치는 형태로 수정해야 한다. 지금 시간이 끌리기 때문에 일단은 넘어가고 추후 보완 개발 때 추가할까 생각중이다. 일단은 매장별로 아이디를 하나씩 줄 예정이니 많지 않을 것이다.


에러가 터질 떄마다 매우 답답하고 힘들다. 기간내에 잘 마쳤으면 좋겠다. 제발 터지지만 않았으면 좋겠다..ㅎㅎ 


반응형