콤마 찍기 (정규표현식)

Web/JavaScript 2021. 2. 22. 13:36 Posted by Request

//콤마찍기
function comma(str) {
    str = String(str);
    return str.replace(/(\d)(?=(?:\d{3})+(?!\d))/g, '$1,');
}

jquery 로 selectBox option 값 찾기

Web/JQuery 2016. 12. 30. 12:47 Posted by Request

jquery 로 selectBox option  값 중 값이 1인 걸 지우는게 가능 할까나?

 

출처 : http://mylife365.tistory.com/112

 

 

Text로 찾을 경우

$("select[name='test'] option:contains('테스트5')").attr("selected", "selected");

 

 

 

 

값으로 찾을 경우

$("select[name='test'] option[value='테스트3']").attr("selected", "selected");

[스크립 주소  ] http://smartjuho.tistory.com/entry/JQuery-%EC%99%80-Prototype-%EC%B6%A9%EB%8F%8C-%EB%B0%A9%EC%A7%80



JQuery와 prototype에서 $()를 사용하려면 충돌이 일어나 스크립트 오류를 일으킨다.

 

둘다 같은 $()를 쓰니까..

 

이를 해결하는 방법은 아래와 같다.

 

jQuery 와 prototype 을 정의한 아래줄에 다음의 소스를 추가한다.

 

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>

 

<script type="text/javascript">
jQuery.noConflict();
var j$ = jQuery;
</script>

 

위와 같이 정의해두면 jQuery에 대한 $()는 -> j$() 로 대체해서 사용할수 잇게된다.

 

물론 충돌도 일어나지 않는다.

 

++ 하지만! jquery의 다른 라이브러리를 다운로드 받아 사용하려면 해당 라이브러리의 $ 를 j$ 로 모두 바꿔줘야 하는 번거로움이 있다.

이는 스크립트를 가져오는 순서만 잘 나열해주면 바로 해결된다.

 

ex)

<script type="text/javascript" src"./js/jquery-1.6.2.min.js"></script> <!-- jquery 기본 라이브러리 -->
<script type="text/javascript" src="./js/jquery-ui-1.8.16.custom.min.js"></script> <!-- 별도로 다운로드 받은 라이브러리 -->

<script type="text/javascript">
jQuery.noConflict();
var j$ = jQuery;
</script>

<script type="text/javascript" src="./js/prototype.js"></script>

 

이런식으로 jquery를 먼저 로드하고 후에 prototype.js 를 로드하면 둘다 문제 없이 사용할 수 있다.


JSTL 태그 - fn

Web/JSP 2016. 8. 9. 18:42 Posted by Request

fn:contains(string, sbustring) 

string이 substring을 포함하면 return True 


fn:containsIgnoreCase(string, sbustring) 

대소문자 관계없이 string이 substring을 포함하면 return True 


fn:endsWith(string, suffix) 

string이 suffix로 끝나면 return True 


fn:escapeXml(string) 

stting에 XML과 HTML에서 특별한 의미를 가진 문자들이 있으면,

XML엔티티 코드로 바꿔준뒤 문자열 반환 


fn:indexOf(string, sbustring)

 string에서 substring이 처음으로 나타나는 인덱스 반환 


fn:join(array, separator) 

array요소들을 separator를 구분자로 하여 연결해서 반환 


fn:length(item) 

item이 배열이나 컬렉션이면 요소의 객수를 문자열이면 문자의 객수를 반환 


fn:replace(string, before, after) 

string내에 있는 before 문자열을 after 문자열로 모두 변경해서 반환 


fn:split(string, separator) 

string내의 문자열 separetor에 따라 나누어서 배열로 구성해서 반환 


fn:startsWith(string, prefix) 

string이 prefix로 시작하면 return True 


fn:substring(string, begin, end) 

string에서 begin인덱스에서 시작해서 end인덱스에 끝나는 부분의 문자열 반환 


fn:substringAfter(string, sbustring) 

string에서 substring이 나타나는 이후의 문자열 반환 


fn:substringBefore(string, sbustring) 

string에서 substring이 나타나는 이전의 문자열 반환 


fn:toLowerCase(string) 

string을 모두 소문자로 바꿔 리턴 


fn:toUpperCase(string) 

string을 모두 대문자로 바꿔 리턴 

 

퍼옴 : http://thdnf1004.tistory.com/entry/JSTL-%ED%83%9C%EA%B7%B8-fn

jQuery serializeArray() 사용 예

Web/JQuery 2016. 8. 4. 10:11 Posted by Request

serializeArray()는

폼안에 입력요소의 값들을 object로 만들어 준다.

 

var fields = j$("#formID").serializeArray();

 

j$.ajax({

url : URL,

type : "POST"

data : fields,

success:function(data){

 

},

error:function(data){

}

});

서버 에러 로그

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'or****': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.***.common.service.***] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}

 

 

 

 

 

 

해결 방법

 

<context:component-scan base-package="egovframework,추가할패키지">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

spring 인터셉터 기능 정리

Web/Spring 2016. 6. 24. 10:02 Posted by Request

ApplicationInterceptor 와 WebContentInterceptor 메모

 

    <mvc:interceptors>
  <!-- 공통 인터셉터 -->
  <mvc:interceptor>
   <mvc:mapping path="/**" />
   <mvc:exclude-mapping path="/resources/**"/>
   <bean class="com.ezwel.core.framework.web.interceptor.ApplicationInterceptor" />
  </mvc:interceptor>


   <mvc:interceptor>
   <mvc:mapping path="/order/**" />
   <mvc:exclude-mapping path="/resources/**"/>
   <bean class="org.springframework.web.servlet.mvc.WebContentInterceptor" >
    <property name="cacheSeconds" value="0" />
    <property name="useExpiresHeader" value="true" />
    <property name="useCacheControlHeader" value="true" />
    <property name="useCacheControlNoStore" value="true" />
   </bean>
  </mvc:interceptor>
 </mvc:interceptors>

Spring Security를 이용한 login 이해

Web/Spring 2016. 3. 10. 13:41 Posted by Request

 

출처 : http://zest133.tistory.com/entry/Spring-Security%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-login1

Spring Security를 이용한 login(1)

Spring Security는 기존 mvc model2에서 일일히 login 관련 한 것들을 알아서 해준다. 예를들어 암호화(hash) 비교, session 체크(cookie 포함), 이중 로그인 체크등 이에 따른 예외 처리등을 관리해준다. 물론 더 많은 기능이 있겠지만, 여기서는 로그인 관련한 것들을 알아보자. 


spring 4.x를 사용하였으며 derby db를 사용했으며 jpa를 사용하며 간단히 만든다. 

먼저 pom 파일에 security관련 lib를 추가하자. 

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
<!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
cs


그리고 web.xml에 security관련 context.xml과 security에 필요한 Filter를 추가한다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml, /WEB-INF/spring/security-context.xml</param-value>
    </context-param>    
....
 <!--생략 ---->
...
    <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


그럼 이제 context.xml을 설정해보자. 먼저 jpa관련 설정을 먼저한다. jpa 관련 설정은 root_context.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
49
50
51
52
53
54
55
56
57
58
59
60
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
 
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
 
        <property name="driverClass" value="org.apache.derby.jdbc.ClientDriver"></property>
        <property name="username" value="user"></property>
        <property name="password" value="gnogun"></property>
        <property name="url"
            value="jdbc:derby://localhost:1527/txtest"></property>
    </bean>
 
    <jpa:repositories base-package="com.gno.sample.repository"
        entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
 
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
 
        <property name="dataSource" ref="dataSource" />
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
                <prop key="hibernate.default_schema">txtest2</prop>
                <prop key="hibernate.connection.pool_size">1</prop>
                <prop key="hibernate.connection.shutdown">true</prop>
                <prop key="hibernate.show_sql">true</prop<!-- SQL 출력 -->
                <prop key="hibernate.ddl_auto">auto</prop>
 
                <!-- 
                <prop key="hibernate.hbm2ddl.auto">create</prop> 
                 -->
 
 
            </props>
        </property>
        <property name="packagesToScan" value="com.gno.sample.dto" />
    </bean>
 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"></property>
 
    </bean>
 
 
 
    
</beans>
 
cs


jpa 설정은 찾아보기로 하고 여기에선 스킵한다. 


servlet-context.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
 
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
 
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    
    <context:component-scan base-package="com.gno.sample" />
    
    <interceptors>
            <beans:bean class="com.gno.sample.security.CustomInterceptor" />
    </interceptors>
    
    
</beans:beans>
 
cs


interceptors 라는 tag가 있는데 controller에서 오는 값을 aop처럼  관리 하지만 security에선 session에 관한 권한 및 session을 관리한다. 이후 소스 부분에 다시 설명하겠다. 


이제 security-context.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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:annotation-config></context:annotation-config>
 
 
<!--  user-expressions 는 intercept-url태그의 access가 true일 경우  
    정의된 함수 ( hasAnyRole, isAnonymous() 등등 ) 를 사용할 수 있게 해준다.  -->
 
    <security:http auto-config='true' use-expressions="true">
<!-- spring 4.x때 추가된 옵션으로 ssl을 사용하지 않을 경우 csrf는 disalbed true로 해준다.  -->
        <security:csrf disabled="true" />
        <!-- autoconfig=false 면? filter도 -->
        <!-- <security:intercept-url pattern="/login" access="isAnonymous()" /> -->
 
 
        <!-- access 이름들은 prefix가 정해져 있음 (default값 ROLE_ ) 재정의 하는 방법은 찾아놨는데 이름을 
            뭘 붙일지 몰라서 그냥 default prefix 사용했음 -->
 
        <security:intercept-url pattern="/admin.do"
            access="hasAnyRole('ROLE_ADMIN')" />
 
        <security:intercept-url pattern="/main.do"
            access="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')" />
 
        
 
        <security:intercept-url pattern="/user.do"
            access="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')" />
 
        <security:intercept-url pattern="/*" access="permitAll" />
        <!-- access="hasAnyRole('ROLE_USER', 'ROLE_ADMIN')" -->
 
        <!-- <security:anonymous /> 
        <security:x509/> 
        <security:http-basic /> 
        <security:session-management></security:session-management> 
            <security:expression-handler ref=""/> 
            <security:custom-filter ref=""/> 
            <security:port-mappings></security:port-mappings> 
            <security:request-cache ref=""/> 
            <security:remember-me/> -->
 
        <!-- always-use-default-target='true' = 서버가 죽었다 살아났을때 기존 가려고 했던 페이지를 무시하고 
            무조건 handler에 정의된 페이지로 이동 -->
<!--authentication-failure-handler-ref와 authentication-success-handler-ref를 사용하지 않을경우는 
authentication-failure-url속성을 사용하여 리다이렉트를 해준다.
  -->
        <security:form-login login-page="/login.do"
            default-target-url="/main.do" authentication-success-handler-ref="loginSuccessHandler"
            authentication-failure-handler-ref="loginFailureHandler"
            always-use-default-target="true" login-processing-url="/loginProcess"
            username-parameter="username" password-parameter="password" />
        <!-- authentication-failure-url="/login" login-processing-url="" password-parameter="" 
            username-parameter="" -->
 
 
 
        <security:logout logout-url="/logout"
            invalidate-session="true"
            success-handler-ref="logoutSuccessHandler" 
            />
 
        <!--
            delete-cookies="JSESSIONID,auth" 
            logout-success-url="/login.do" />
         delete-cookies="" logout-url="" invalidate-session="true" success-handler-ref="" -->
 
    </security:http>
 
    <security:authentication-manager>
 
        <!-- <security:authentication-provider ref="userProvider"> </security:authentication-provider> -->
        <security:authentication-provider
            ref="CustomAuthenticationProvider">
        </security:authentication-provider>
 
 
    </security:authentication-manager>
<!--
    provider는 이미 form에서 id 및 pwd(암호화 된값)을 가져오고 db에서 가져온 값을 UserService를 통해  UserDetail을 저장을 하며
    UserDetail은 인증정보(db에서 가져온 사용자 값) 과 권한정보를 
    가져와서 provider는 먼저 인증을 비교한후  true가 되면 권한(Grant Authority)을 부여한다.      
      
 -->
    <bean id="CustomAuthenticationProvider" class="com.gno.sample.security.CustomAuthenticationProvider">
        <property name="userDetailsService" ref="userService"></property>
        <property name="passwordEncoder" ref="passwordEncoder"></property>
    </bean>
<!-- UserDeatilService(com.gno.sample.security.CustomUserDetailService) 클래스는 
    인증(authentication)에 사용할 UserDetails 객체를 생성하는 작업이고 , 
    UserDetails는 db에서 id값으로 user의 정보 및  권한(authority)정보를  저장한다.   
    이상 스러운건 이미 암호화 값으로 변경이 되있다.  -->
    <bean id="userService" class="com.gno.sample.security.CustomUserDetailService" />
 
    <bean id="passwordEncoder"
        class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
 
    <bean id="loginSuccessHandler" class="com.gno.sample.security.LoginSuccessHandler"></bean>
    <bean id="loginFailureHandler" class="com.gno.sample.security.LoginFailureHandler"></bean>
    <bean id="logoutSuccessHandler" class="com.gno.sample.security.CustomLogoutSuccessHandler"></bean>
</beans>
 
cs

굉장히 많은거 같은데 한개씩 보도록 하자. 

먼저 security:http  태그를 살펴보자. 속성으로 auto-config라는 넘이 있다 

이넘이 true 일경우 filter는 defalut 값으로 되며 만약 false라면 

<security:anonymous /> 

<security:x509/> 

<security:http-basic /> 

<security:session-management></security:session-management> 

<security:expression-handler ref=""/> 

<security:custom-filter ref=""/> 

<security:port-mappings></security:port-mappings> 

<security:request-cache ref=""/> 

<security:remember-me/> 

위의 filter들을 셋팅해줘야 한다. 


다음 속성으로 user-expressions 라는 속성은 만약 false라면 spring에서 제공하는 hasAnyRole,isAnonymous() 등 내부 함수를 사용하지 못한다.  하지만 보통은 사용하므로 true로 해준다. 


csrf는 spring4.x에 추가된 태그로 ssl등을 사용하지 않을때는 disabled=true로 설정을 해준다. 


다음은 interceptor-url 이다. 이 태그는 각 url별 권한( autority)를 부여해준다. 그리고 높은 권한일 경우 먼저 써주고 낮은 권한 일 경우 아래에 써주는 것을 권장 하고 있다. 위의 설정 파일을 보면 ADMIN 권한 먼저 그다음 ADMIN과 User 그다음은 permitAll 로 주고 있다. 만약 순서가 잘못되면 권한 문제로 페이지가 잘못 나올경우 있으니 주의 하자. 


그리고 login과 logout은 각 handler가 존재한다. 먼저 login을 살펴보자. 


속성 

설명 

 login-page

로그인 page

 default-target-url

로그인 성공시 이동할 url 설정 

 authentication-success-handler-ref

로그인 성공시에 대한 프로세스 정의 보통 권한이 많을 경우 이 핸들러에서 redirect로 설정하며, defalut-target-url은 사용하지 않는다. 

 authentication-failure-handler-ref

로그인 실패시에 대한 프로세스 정의  

 always-use-default-target

WAS 서버가 죽었다  살아 났을때 기존 가려고 했던 페이지는 무시하고 무조건 핸들러에 정의된 페이지로 이동

 login-processing-url

 로그인 처리에 대한 url 어떠한 controller 든지 이런것은 정의 되지 않지만 로그인 form 내에서 action url은 이 url로 정의 되야 하며 내부적으로 이 url로 로그인 processing이 진행된다. 

 username-parameter, password-parameter

만약 이 파라미터가 없다면 스프링에서 제공되는 j_username, j_password를 사용해야한다.  

 


logout은 invalidate-session의 경우 logout이 진행되면 session 정보를 설정값에 따라 삭제를 진행한다. true일경우 삭제. 


암호화 방식은 bean으로 설정을 하며, 위의 설정 파일에는 id는 passwordEncoder이며 암호화 방식 bcrypt를 사용한다. 


자 이제 마지막으로 3가지가 등장한다. AuthenticationProvider, UserService, UserDetail 이 존재한다. 

provider는 이미 form에서 id 및 pwd(암호화된 값)과 db의 값을 비교한후 true이며 권한(Grant Autority)를 부여한다. 이때 비교를 하기위해 참조값으로 암호화 방식의 bean을 등록해야한다. 

UserService는 인증(authentication)에 사용할 UserDetail 객체를 생성한다. 

UserDeatil은 user의 정보 및 권한 정보를 저장한다.


여기까지 설정은 모두 끝났다. 다음 글에서 소스를 살펴보자.

 

Action 비지니스 처리

Web/JSP 2016. 1. 12. 13:50 Posted by Request

HttpSevletRequest req = getRequest();

 

req.setAttribute("searchList",dataService.getList(searchBean));

 

 

1.JSP 기본 객체의 속성 값 지정이 아직도 어색하다니..

setAttribute(String name, Object value) 이름이 name 속성의 값을 value 로 설정

getAttribute(String name) - 이름 name인 속성의 값을 가져온다.

getAttrubuteNames() - 속성의 이름 목록을 가져온다.

 

2.속성에 대한 범위 지정

pageContext - 하나의 페이지 내에서 공유 될 값 . 주로 custom tag 에서 새로운 변수 추가 할때 사용.

request - 한번 의 요청을 처리하는 되 사용되는 모든 페이지에서 공유될 값. 페이지 사이에서 정보 전달하기 위해 사용.

session - 한 사용자와 관련된 정보를 공유할 때 사용.

application - 모든 사용자 와 관련해서 공유할 정보를 저장.

 

 

http://woosa7.tistory.com/60

 

 

 

[출처 : http://zgundam.tistory.com/m/post/51]


이 화면은 로그인 화면에서 로그인이 정상적으로 이루어진 뒤에 자동으로 메인화면으로 이동했을때 로그인 폼이 그대로 나타나고 있기 때문에 로그인이 정상적으로 되었는지 알 수가 없다. 이 부분을 이제 바꾸어보도록 하겠다.


1. Custom Tag를 등록한다.

-Spring Security에서는 jsp 페이지에서 사용할 수 있는 Custom Tag를 제공한다.


<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>


=> 공통 include 파일이든 또는 Spring Security의 기능을 jsp 페이지에서 써야 하는 곳에서든 저 코드를 넣어서 Spring Security가 제공하는 tag를 사용할 수 있게해준다.


 먼저 Spring Security에서 로그인 정보를 가져오는 방법에 대해 설명하도록 하겠다. 2가지의 방법이 있는데 Spring Security가 자체적으로 제공하는 방법과 HttpServletRequest 객체에서 가져오는 방법이렇게 2가지가 있다.


Servlet Spec 2.5에서는 인증 과정을 마치고 난 뒤의 로그인 정보를 가져오는 기능만 있었으나 Servlet Spec 3.0 이상에서는 Spring Security가 제공하는 인증 기능을 이용해 로그인 하거나 로그아웃 하는 기능도 사용할 수 있다. 

Servlet Spec 3.0 이상을 사용하는 WAS는 Tomcat 7.0 이상을 사용하면 된다. 


Spring Security가 자체적으로 제공하는 방법

<%@ 
page import="org.springframework.security.core.context.SecurityContextHolder" %>
<%@ page import="org.springframework.security.core.Authentication" %>
<%@ page import="com.terry.springsecurity.vo.MemberInfo" %>
<%
Authentication auth = SecurityContextHolder.getContext().getAuthentication();

Object principal = auth.getPrincipal();	
String name = "";
if(principal != null && principal instanceof MemberInfo){
	name = ((MemberInfo)principal).getName();
}
%>



위의 코드에서 보듯이 HttpServletRequest 클래스의 getUserPrincipal() 메소드를 이용해서 인증 정보를 가져오고 있다. 
로그인이 성공했을 경우엔 두 방법 모두 org.springframework.security.authentication.UsernamePasswordAuthenticationToken 객체를 받아온다.
 그러나 로그인을 하지 않은, 즉 Anonymous 사용자인 경우엔 두 가지 방법에 차이점이 존재한다.Anonymous 사용자인 경우 Spring Security를 이용하는 방법에서는 org.springframework.security.authentication.AnonymousAuthenticationToken 객체가 return 되지만 HttpServletRequest를 이용하는 방법에서는 null이 return 되기 때문이다. 그래서 Spring Security를 이용하는 방법에서는 인증 정보를 받는 변수인 auth에 대한 null 체크를 하지 않지만 HttpServletRequest를 이용하는 방법에서는 인증 정보를 받는 변수인 auth에 대한 null 체크를 하게 되는 것이다.

<div style="width:200px;float:left;">

<sec:authorize access="isAnonymous()"> <form id="loginfrm" name="loginfrm" method="POST" 

action="${ctx}/j_spring_security_check"> <table> <tr> <td style="width:50px;">id</td> <td style="width:150px;"> <input style="width:145px;" type="text" id="loginid" name="loginid" value=""/> </td> </tr> <tr> <td>pwd</td> <td> <input style="width:145px;" type="text" id="loginpw" name="loginpw" value=""/> </td> </tr> <tr> <td colspan="2"> <input type="submit" id="loginbtn" value="로그인" /> </td> </tr> </table> </form> </sec:authorize> <sec:authorize access="isAuthenticated()"> <%=name%>님 반갑습니다<br/> <a href="${ctx}/j_spring_security_logout">로그아웃</a> </sec:authorize> <ul> <sec:authorize access="hasRole('ROLE_ADMIN')"> <li>관리자 화면</li> </sec:authorize> <sec:authorize access="permitAll"> <li>비회원 게시판</li> </sec:authorize> <sec:authorize access="isAuthenticated()"> <li>준회원 게시판</li> </sec:authorize> <sec:authorize access="hasAnyRole('ROLE_MEMBER2', 'ROLE_ADMIN')"> <li>정회원 게시판</li> </sec:authorize> </ul> </div>

 로그인 id test1에 준회원 권한을 DB에서 설정해 둔 뒤에 로그인을 한 모습이다. 
로그인 한 사람의 이름(테스트1)을 보여주고 있고 로그아웃 링크를 보여주고 있다. 또 준회원 권한(ROLE_MEMBER1)을 가지고 있기 때문에 비회원 게시판과 준회원 게시판 메뉴를 보여주고 있다. 관리자 권한(ROLE_ADMIN)을 주면 정회원 게시판과 관리자 화면 메뉴도 나타날 것이다. 이렇게 권한을 이용한 동적 메뉴 화면 모습을 보여주고 있다. 잘 이해가 안되면 <sec:authorize> 태그 설명한 부분을 다시 한번 읽어보면서 화면과 매핑을 시켜보면 이해가 될 것이라고 생각한다.


이제는 로그아웃을 설명할 차례이다. 지금까지 블로그에서 설명하면서 화면상에서 로그아웃을 보여주는 부분이 없어서 로그아웃에 대한 설정을 설명할 일이 없었으나 이제는 로그아웃이 언급되다보니 로그아웃 설정에 대한 설명을 할 시점이 되었다. 로그아웃을 실행시킬려면 j_spring_security_logout 으로 링크를 걸면 로그아웃 기능을 수행한다(j_spring_security_logout 이란 문자열이 길어서 거부감이 있다면 이것도 바꿀수 있다. 곧 이어 설명할 logout 태그의 logout-url 속성에 원하는 값을 지정해주면 된다. 이 속성의 default 값이 j_spring_security_logout 이다). 또한 로그아웃에 대한 설정을 <http> 태그 안에 다음과 같은 내용으로 넣도록 한다.

<logout 

	logout-success-url="/main.do"
	delete-cookies="JSESSIONID"
/>


logout-success-url 속성은 로그아웃 작업을 마친 뒤에 보여지는 화면 URL을 설정한다.

 delete-cookies는 로그아웃을 진행하면서 지워야 할 쿠키를 지정하는 속성이다. ,를 구분자로 하여 여러개의 쿠키 이름을 지정하면 된다. WAS를 통해 웹브라우저로 웹페이지를 보면 JSESSIONID란 이름의 쿠키가 내려오는데 로그아웃을 하면서 이 쿠키도 같이 정리하기 위해 delete-cookies 속성에 지정하는 것이다. 만약 다른 이름의 쿠키가 내려오거나 또는 사이트에서 로그인을 하면 내부적으로 특정 쿠키를 생성해서 작업하고 있다면 이 delete-cookies 속성을 이용해서 그런 부류의 쿠키를 지울수가 있는 것이다.