====== Spring Security ====== * 현재 페이지는 Spring Security 3.x 기준 * [[springframework:security:customfilter|Spring Security Custom Filter]] ===== http ===== * 에서 **filters="none"**이면 해당 URL에서는 Spring Security 관련 기능이 아무것도 작동하지 않게 된다. ===== Session 폭증 문제 ===== Spring Security는 로그인시 예외를 비롯해 많은 정보를 세션(HttpSession)에 저장한다. 이 경우 로그인이 공격 대상이 될 때 로그인 URL에서 세션을 폭발적으로 생성하게 되고 이로인해 메모리 폭증이 발생한다. 이는 결과적으로 다시 매우 잦은 Full GC를 유발하게 된다. 따라서 공격에 노출될 가능성이 있는 사이트는 최소한 로그인의 경우에 세션을 생성하지 않도록 다양한 처리가 필요하다. 혹은 세션을 생성하더라도 공격시도는 Spring Security를 타기전에 다른 방법으로 차단할 수 있어야 한다. 로그인시에 세션에 저장하는 값들은 [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/WebAttributes.html|WebAttributes]]의 상수들 참조. ==== 설정에서 세션 생성하지 않도록 ==== 설정에서 ''create-session="never"'' 를 준다 이렇게 하면 [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.html|UsernamePasswordAuthenticationFilter]]의 ''allowSessionCreation'' 값 등이 false로 변경된다. ===== Expression Handler ===== * Writing your spring security expression language annotation [[http://borislam.blogspot.hk/2012/08/writing-your-spring-security-expression.html|Part 1]] [[http://borislam.blogspot.hk/2012/08/writing-your-spring-security-expression_9.html|Part 2]] [[http://borislam.blogspot.hk/2012/08/writing-your-spring-security-expression_17.html|Part 3]] * [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/access/expression/WebSecurityExpressionRoot.html|WebSecurityExpressionRoot]]를 상속하여 표현식 함수를 추가한다. * [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.html|DefaultWebSecurityExpressionHandler]]를 상속하여 Expression Handler를 만든다. ==== global-method-security에 핸들러 지정 ==== * [[http://stackoverflow.com/questions/6632982/how-to-create-custom-methods-for-use-in-spring-security-expression-language-anno|java - How to create custom methods for use in spring security expression language annotations]] 참조 ==== http에 핸들러 지정 ==== * SpringSecurity 3.0 에서는 XML 태그를 통해 웹 전반에 관한 expressionHandler 설정이 불가능 하다. [[https://jira.springsource.org/browse/SEC-1452|SEC-1452 버그 참조]]. 3.1부터 가능. * access-decision-manager-ref를 지정함으로써만 가능하다. 다음 참조. ... ROLE_A > ROLE_B ROLE_B > ROLE_AUTHENTICATED ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED ===== Access Denied Handler ===== * 권한이 없을 경우 발생하는 에러를 잡아서 처리하는 핸들러를 지정할 수 있다. * 지정안하면 기본적으로 ''403 Forbidden'' 페이지가 뜬다. * * [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/access/AccessDeniedHandler.html|org.springframework.security.web.access.AccessDeniedHandler]]를 구현하여 Bean으로 등록하면 된다. * 에러처리 컨트롤러 주소 지정시에는 [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/WebAttributes.html#ACCESS_DENIED_403|WebAttributes.ACCESS_DENIED_403]] 키로 request객체의 속성을 받아서 [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/access/AccessDeniedException.html|AccessDeniedException 예외 객체]]를 구할 수 있다. ===== Session에 예외 객체 저장현상 ===== SpringSecurity는 로그인 혹은 권한 관련예외가 발생할 경우 세션에 해당 예외를 저장한다. ([[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.html|SimpleUrlAuthenticationFailureHandler]]의 saveException() 참조) 해당 예외는 [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/WebAttributes.html#AUTHENTICATION_EXCEPTION|WebAttributes.AUTHENTICATION_EXCEPTION]]의 값인 ''SPRING_SECURITY_LAST_EXCEPTION''으로 저장된다. 문제는 기계화된 로그인 공격이 들어올 경우 모든 리퀘스트는 새로운 세션으로 간주되며 로그인 실패 예외들이 모두 세션에 저장되어 메모리 고갈을 일으킨다는 점이다. 이 때문에 [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/authentication/AuthenticationFailureHandler.html|AuthenticationFailureHandler]]를 [[http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/authentication/SimpleUrlAuthenticationFailureHandler.html|SimpleUrlAuthenticationFailureHandler]]를 상속하여 구현하면서 ''saveException()''을 호출하지 않도록 하는 것이 좋다. 혹은 설정에서 ''create-session="never"'' 를 준다 ==== 아예 세션에 로그인 실패 예외를 저장하지 않도록 ==== saveException()을 호출하지 않도록 처리한 구현체를 다음과 같이 설정해 준다. 이는 로그인 실패에 대한 것이며 권한 없음에 대한 예외는 다른 문제이다. ==== JSP에서 삭제 ==== JSP에서 저장된 예외를 메시지 출력에 사용하는 경우가 있을 수 있는데, 이때는 JSP에서도 삭제하도록 해야 한다. ===== Session 직접 구현 ===== * ConcurrentSessionFilter -> SecurityContextRepository ===== @AuthenticationPrincipal ===== * [[https://www.javacodegeeks.com/2016/09/injecting-authenticated-user-spring-mvc-controllers.html|Injecting authenticated user into Spring MVC @Controllers]] * Controller 에 로그인 사용자 객체를 주입할 수 있다. ===== 참고 ===== * [[http://www.javabeat.net/spring-security-tutorial/|Spring Security Tutorial]] * [[https://www.baeldung.com/spring-security-oauth2-enable-resource-server-vs-enable-oauth2-sso|OAuth2 - @EnableResourceServer vs @EnableOAuth2Sso | Baeldung]] * [[https://javatechonline.com/how-to-implement-security-in-spring-boot-project/|How to implement Security in Spring Boot Project? | Making Java easy to learn]] * [[https://www.baeldung.com/spring-session|Guide to Spring Session | Baeldung]]