JSP 소스와 같은 경로내의 파일을 읽어오려고 할때 ./ 를 쓰고 싶지만
그럴때마다 No such file or directory 에러를 만난다.
Spring Security Custom Filter
Spring Security Custom Filter
스프링 시큐리티의 필터를 재정의 하거나 혹은 원하는 대로 추가할 수 있다.
기본 필터
Alias | Filter Class | Namespace Element or Attribute |
---|---|---|
CHANNEL_FILTER | ChannelProcessingFilter | http/intercept-url@requires-channel |
CONCURRENT_SESSION_FILTER | ConcurrentSessionFilter | session-management/concurrency-control |
SECURITY_CONTEXT_FILTER | SecurityContextPersistenceFilter | http |
LOGOUT_FILTER | LogoutFilter | http/logout |
X509_FILTER | X509AuthenticationFilter | http/x509 |
PRE_AUTH_FILTER | AstractPreAuthenticatedProcessingFilter Subclasses | N/A |
CAS_FILTER | CasAuthenticationFilter | N/A |
FORM_LOGIN_FILTER | UsernamePasswordAuthenticationFilter | http/form-login |
BASIC_AUTH_FILTER | BasicAuthenticationFilter | http/http-basic |
SERVLET_API_SUPPORT_FILTER | SecurityContextHolderAwareFilter | http/@servlet-api-provision |
REMEMBER_ME_FILTER | RememberMeAuthenticationFilter | http/remember-me |
ANONYMOUS_FILTER | AnonymousAuthenticationFilter | http/anonymous |
SESSION_MANAGEMENT_FILTER | SessionManagementFilter | session-management |
EXCEPTION_TRANSLATION_FILTER | ExceptionTranslationFilter | http |
FILTER_SECURITY_INTERCEPTOR | FilterSecurityInterceptor | http |
SWITCH_USER_FILTER | SwitchUserFilter | N/A |
-
FORM_LOGIN_FILTER
는 로그인 시도가 왔을 경우, 성공/실패와 무관하게 기본적으로는 그 뒤에 오는 필터를 실행하지 않고 리턴한다. 따라서 로그인과 관련된 것중 필히 시도해야 하는 것은FORM_LOGIN_FILTER
에 대해 before로 지정해야 한다.
재정의 하는 법
기존 필터를 상속하거나 Filter를 직접 구현하여 Bean 으로 생성한다. 위치 Alias
에는 위 표에 나온 대문자 상수들을 지정한다.
<http ...> <custom-filter ref="생성한필터Bean" 위치지시자="위치Alias" /> </http>
-
위치 지시자
-
before
는 위치 Alias보다 앞에, -
after
는 뒤에 -
position
은 해당 위치에 있는 필터 대체
-
-
추가 위치 Alias
-
FIRST
: 맨 앞 -
LAST
: 맨 뒤
-
-
position
을 사용하는 경우에는auto-config=“false”
로 해서 모든 것을 개발자가 직접 설정 해줘야 한다.
web.xml session-timeout [세션타임 설정]
<session-config>
<session-timeout>1</session-timeout>
</session-config>
spring security ajax session timeout 체크 방법
웹 애플리케이션에서 사용자 세션 만료 시 로그인 페이지로 강제 이동시키는 경우가 있다.
만약 ajax를 이용하여 서버와의 비동기 방식으로 통신하는 경우 사용자 세션이 만료되어 있다면 이를 어떻게 처리해야 할까?
스프링 시큐리티에서 커스텀 필터를 등록하여 사용자 세션 만료에 대한 exception을 catch한 후 예외 처리 하는 방법으로 ajax 통신에 대한 세션 타임 아웃 체크가 가능하다.
security-context.xml
<security:http>
<!– check session time out with ajax –>
<security:custom-filter after=“EXCEPTION_TRANSLATION_FILTER” ref=“ajaxSessionTimeoutFilter”/>
</security:http>
<bean id=“ajaxSessionTimeoutFilter” class=“com.kyu.svc.common.filter.AjaxSessionTimeoutFilter”>
<property name=“ajaxHeader” value=“AJAX” />
</bean>
client에서의 request 요청 시 header name 중 AJAX가 있는지 여부를 체크하기 위해서 ajaxHeader property 셋팅
AjaxSessionTimeoutFilter.java
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (isAjaxRequest(req)) {
try {
chain.doFilter(req, res);
} catch (AccessDeniedException e) {
res.sendError(HttpServletResponse.SC_FORBIDDEN);
} catch (AuthenticationException e) {
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
} else {
chain.doFilter(req, res);
}
}
private boolean isAjaxRequest(HttpServletRequest req) {
return req.getHeader(ajaxHeader) != null && req.getHeader(ajaxHeader).equals(Boolean.TRUE.toString());
}
로그인 된 사용자의 세션이 만료되면 spring security에서는 AccessDeniedException 예외를 발생시키고 AjaxSessionTimeoutFilter가 이를 catch하여 response로 에러 코드 403을 return한다.
jsp
$(‘#start’).click(function() {
$.ajax({
type : “GET”,
url : “${contextPath}/test/progressbar.json”,
dataType : “json”,
success : function(response) {
alert(response.result);
}
});
});
jquery-common.js
(function($) {
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader(“AJAX”, true);
},
error: function(xhr, status, err) {
if (xhr.status == 401) {
alert(“401”);
} else if (xhr.status == 403) {
alert(“403”);
} else {
alert(“예외가 발생했습니다. 관리자에게 문의하세요.”);
}
}
});
})(jQuery);
모든 ajax 요청 전 beforeSend 함수가 호출되고 request 헤더에 AJAX를 셋팅해 준다.
ajax 요청 후 사용자 세션이 만료되어 있다면 HTTP status 403을 return하게 되고, client는 이를 받아 로그인 페이지로 이동시키면 되는 것이다.
$.ajaxSetup의 error function 에서 모든 ajax 요청에 대한 error를 처리하기 때문에 해당 코드를 외부 js로 분리한 후 공통 js로 사용한다면 중복 코드 없이 ajax session timeout 체크가 가능할 것이다.
org.apache.jasper.JasperException: No message found under code, No message found under code … for locale ‘ko’.
Spring 에서 Java Locale 정보 취득하기
import java.util.Locale; import org.springframework.context.i18n.LocaleContextHolder; public class LocaleTest { public Locale getLocale() { return LocaleContextHolder.getLocale(); } }
스프링 다국어 처리 – localeResolver, messageSource
스프링에서 다국어를 처리하려면
LocaleChangeInterceptor + messageSource
조합으로 가능하다.
국가별로 페이지들 별도로 만드는짓은 더이상 하지 말자.
만약 서버단에서 위의 조합으로 다국어 처리된 문자열을
jsp단으로 보내주고 싶을 경우에는
추가로 taglib를 사용하면 된다.
1. LocaleResolver
말그대로 현재 접속된 사용자에게 적합한 언어셋을 제공하기 위해
브라우저의 useragent 값이나 쿠키, 세션을 통해 locale 값을 처리한다.
그래서 우선 해당 xml에 아래처럼 추가해준다.
<applicationContext.xml>
<mvc:interceptors> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="lang"></property> </bean> </mvc:interceptors> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>
localeResolver의 종류는 3가지가 있다.
defalut는 AceeptHeaderLocaleResolver이다.
reqest 헤더의 accept-language부분에서 locale을 읽어온다.
나머지는 이름 그대로 쿠키나 세션을 사용한다.
<bean id="localeResolver"font-size:12px;">AcceptHeaderLocaleResolver" />
<bean id="localeResolver" font-size:12px;">CookieLocaleResolver" > <property name="cookieName" value="clientlanguage"/> <property name="cookieMaxAge" value="100000"/> <property name="cookiePath" value="web/cookie"/> </bean>
<bean id="localeResolver" font-size:12px;">SessionLocaleResolver" />
2. MessageSource
locale값이 정해지면 Spring에서해는 해당 locale의 messagesource의 값으로 변환해서 돌려준다.
그래서 우선 localechangeinterceptor처럼 xml에 등록먼저 해주자.
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="WEB-INF/messages/Messages"/> <property name="defaultEncoding" value="UTF-8" /> <property name="cacheSeconds" value="180"/> </bean>
※ basename : Messages 파일 위치
본인의 설정에서는
WEB-INF/messages폴더밑에
‘Messages_[locale]’ 형태의 파일을 만들었다.
ko와 en두가지 버전이 있다.
만약 locale값이 ko,en이 아닐 경우
맨 마지막에 있는 Message.properties를 참조하게 된다.
왼쪽은 변수명이고,
오른쪽은 locale값이 ko 일경우에
돌려주는 값이다.
Messages 파일에서는 영어가 아닐 경우
자동으로 유니코드값으로 변환되어 기록된다.
그러나 출력시에는 저렇게 유니코드값이 아닌 정상적으로 출력된다.
3. message 호출
위처럼 만들고 써먹으려면 아래 함수를 호출하면 된다.
code는 2번에서 작성한 좌측의 변수명이고
locale은 말그대로 locale이다
import org.springframework.context.MessageSource; ...... messageSource.getMessage(code, null, locale)
임의적으로 locale값을 설정하고 싶으면
localeResolver.setLocale(request, response, Locale.KOREA);
처럼 하면 된다.
4. jsp에서 처리 (taglib)
localeResolver와 message 프로퍼티 설정이 끝나면
jsp에서도 바로 다국어 처리가 가능하다.
우선 jsp 상단에
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
를 추가하고,
다국어 처리가 필요한 부분에
<spring:message code="code_name"/>
를 삽입해주면 된다.
Spring Security – 한 유저 동시 접속 막기
만약 한명의 유저가 여러번 로그인하는 것을 막고 싶다면 아래와 같이 설정한다.
먼저 web.xml 에 listener를 등록한다.
<listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener>
다음으로 Application Context에 아래 태그를 추가한다.
<http> ... <session-management> <concurrency-control max-sessions="1" /> </session-management> </http>
이렇게 하면 두번째 로그인 시 먼저 로그인한 것은 무효화된다.
만약 나중에 로그인 한 것을 막고 싶다면 아래와 같이 설정한다.
<http> ... <session-management> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> </session-management> </http>
이러한 설정으로 인해 거부된 사용자는 form-based login방식이 쓰여지고 있다면 authentication-failure-url 로 보내지게 되는데, 그렇지 않다면 402에러와 같은 내용이 사용자에게 전달된다. 만약 에러페이지를 설정하고 싶다면, session-management 요소에 session-authentication-error-url 속성을 추가하면 된다.
스프링 시큐리티 중복로그인, 세션 관리하기 설정법
세션 관리타임아웃 감지하기스프링 시큐리티에서 유효하지 않은 세션 ID를 감지하고 적절한 URL로 리다이렉트 시키도록 설정할 수 있다. 이것은 session-management 엘리먼트를 사용한다. |
<http> ... <session-management invalid-session-url="/sessionTimeout.htm" /> </http>
동시 세션 제어사용자가 동시에 한번만 로그인할 수 있도록 제한하고 싶으면, 스프링 시큐리티는 다음과 같이 간단하게 추가할 수 있도록 지원한다. 세션 생명주기와 관련된 이벤트를 스프링 시큐리티가 받을 수 있도록 하기 위해, 우선 다음의 리스너를 web.xml 파일에 추가할 필요가 있다. |
<listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener>
그리고 애플리케이션 컨텍스트에 다음의 코드를 추가한다. |
<http> ... <session-management> <concurrency-control max-sessions="1" /> </session-management> </http>
이것은 한 사용자가 동시에 두번 로그인 하는것을 방지한다. (두번째 로그인으로 인해 첫번째 로그인은 무효화된다) 종종 두번째 로그인을 방지할 필요가 있는데, 그런 경우에는 다음과 같이 할 수 있다. |
<http> ... <session-management> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> </session-management> </http>
그러면 두번째 로그인은 거부될 것이다. “거부”될 경우는, 폼-기반 로그인이 사용되는 환경에서는 authentication-failure-url 로 보내진다. 만약 두번째 로그인이 “remember-me”와 같은 비-상호적 메커니즘에 의해 수행되었다면, “unauthorized(불허가)”(402) 에러가 발생할 것이다. 대신에 에러페이지를 사용하려면 session-management 엘리먼트의 session-authentication-error-url 속성을 추가할 수 있다.
만약 폼-기반 로그인에 직접 작성한 인증 필터를 사용한다면, 동시 세션 제어 기능을 명시적으로 설장할 수 있다. 더 자세한 사항은 세션관리 장에서 찾을 수 있다. Session Fixation Attack 방지악의적인 사용자가 사이트에 접근하기 위한 세션을 만들고, 그 세션을 통해 다른 사용자로 로그인 하려고 하는 경우(예를 들어, 세션에 ID를 파라미터로 포함하여 전송하는 경우) Session fixation attack의 잠재적인 위험이 존재하게 된다. 스프링 시큐리티는 이러한 공격을 자동으로 막기 위하여 사용자 로그인 때마다 새로운 세션을 생성한다. 이러한 방지 기능이 필요하지 않거나, 다른 기능들과 충돌이 발생할 경우에는, <session-management>의 session-fixation-protection 속성값으로 동작을 제어할 수 있다. 속성은 다음과 같은 세가지 옵션값들을 가진다.
|
로또 4등 당첨 후기….
지난 1월 30일 … 내 생일날..
와이프와 간만에 외식도 할겸 시내나가서 외식을 하기전에
주머니에있는 5천원짜리… 한장…으로
로또 자동으로 ㅋㅋ 샀었죠…
처음 4등 당첨이라 너무 좋았네요 ㅋㅋ 바로 판매점가서 5만원 받아서 만난거 사먹어야지.. ㅋ
5등은 몇번 당첨되봐서.. 좋았는데 이번에는 번호가 4개 맞으니까.. 심장이 벌렁이면서
호..혹…혹시…!?? ㅋㅋ 4등도 좋습니다.. 왜냐하면… 아무생각이 없기 때문이다.. ㅋ
1등 일확천금.. 그런 쓸데 없는 상상보다는 그냥 소소하게 당첨이 되는 재미로 사야하기 때문이죠 ㅋ
여러분 너무 돈욕심 부리지 마세요…ㅎㅎ
(응?? 근데 로또 용지 어디다 둔거지 ㅠ ㅠ;;;;;;;; )