Spring Security - Filters ( DelegatingFilterProxy, FilterChainProxy )

이미지
이번 글에서는 Spring Security Filter Chain 에 대해서 정리를 하려고 한다. https://spring.io/guides/topicals/spring-security-architecture Spring Security web infrastructure 는 Servlet  filter 기반이다.   아래의 이미지를 보면, http request 가 어떻게 처리 될 지 명백하게 이해할 수 있을것이다.  Client 는 Application 으로 요청을 보낸다. 그리고 해당 요청은 어떤 filter 들과 어떤 servlet 이 적용되야 하는지 request URI 에 따라서 판별된다. 최대 하나의 servlet 은 하나의 request 만 처리할 수 있지만, filter 는 chain 을 이루고 순서가 지정되며 실제로 request 자체를 처리할 때 filter 가 나머지 chain 이 처리 되지 않도록 할 수 있다. filter 는 이후에 적용될 filter 및 servlet 에 사용 될 request 와 response 를 수정할 수도 있다. 따라서 filter chain 의 순서는 매우 중요하다. Spring Boot 에서는 두 가지 메커니즘을 통해 filter chain 을 관리한다. Filter Type 의 @Beans 은 @Order 를 가지거나 Ordered 를 구현한다. one is that  @Beans  of type  Filter   can have an   @Order  or implement  Ordered Filter 들이 API 의 일부로서 순서를 갖는 FilterRegistrationBean 의 일부가 될 수 있다. the other is that they can be part of a  FilterRegistrationBean  that itself has an order as part of its A...

Spring Security - OAuth2 && JWT (JSON Web Token) - 2

이미지
지난 글에서  https://infondgndg91.blogspot.com/2020/06/spring-security-oauth2-jwt-json-web.html 간단하게 OAuth 2.0 과 JWT (Json Web Token) 에 대해 정리를 해보았다. 이번 시간에는 OAuth 2.0 4가지 type 중 간단한, Resource Owner Password Credentials Grant 를 구현하려고 한다. 먼저 인증 서버에 대한 구현이다. 간단하게 개발 스펙을 정리해보자면, Spring Boot 2.3.1.RELEASE  Java 14 guava 와 commons 는 애용해서 넣었다. 그리고 auth0 의 JWT, DB 는 mysql 을 사용했다. 당연히 security 와 web 을 추가했다. 그밖에, 롬복, 데브툴, 컨피규레이션 프로세서는 개발 시 많은 유용함이 있어서 당연히 사용했다. 다음은 application.yml 이다. 우선 jwt 와 관련된 내용들이며, 다음은 DataSource 내용들이다. DB 는 AWS RDS 를 사용했고, write 와 read 클러스터 구성이다. 따라서 write 와 read 를 각각 설정해주었다. 로깅은 개발 시 로깅을 디테일하게 켜서 보려고 해놓은거라서 중요한 것은 아니다. 그렇다면, 먼저 DataSource 설정이다. JdbcTemplate 을 사용려고 각각의 DataSource 마다 JdbcTemplate 을 Bean 으로 이용했다. 그 다음, 시큐리티 설정을 확인하자. AuthenticationProvider 를 구현한 커스텀 JWTAuthenticationProvider 을 사용했다. OAuth 2.0 Token 기반 인증 방식을 사용하기 때문에, 세션은 당연히 StateLess 무상태이다. csrf, header, formlogin 모두 disabled 했다. AuthenticationEntryPoint 를 구현하는 핸들러와 AccessDeniedHandler 를 구현하는 핸들러를 통해서...

Spring Security - OAuth2 && JWT (JSON Web Token) - 1

이미지
spring security 를 통해서 OAuth2 구현을 해 볼 예정이며, 먼저 이번 글에서는 OAuth2 개념과 JWT 개념에 대해서 정리해보려고 한다.  OAuth 2 란? OAuth 2.0 권한 부여 프레임워크를 사용하면 타사 애플리케이션의 자원 소유자와 HTTP 서비스 간의 승인 상호 작용을 조정해 자원 소유자를 대신해 HTTP 서비스에 대한 제한된 접근 권한을 얻거나 타사 애플리케이션이 자체적으로 접근 권한을 얻는다. 해당 사양은 RFC 5849, The OAuth 1.0 Protocol 에 설명된 더 이상 사용하지 않는 OAuth 1.0 프로토콜을 대체한다.      The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf. This specification replaces and obsoletes the OAuth 1.0 protocol described in RFC 5849 . https://tools.ietf.org/html/rfc6749 OAuth 2 를 활용하는 방법을 제대로 이해하려면 특정 역할과 역할 간의 관계를 이해해야 한다. 그렇다면, 각 권한 부여 프로세스에 참여하는 역할을 살펴보자. OAuth defines four roles: resource owner An entity capable of granting access to a pro...

Spring Security - UserDetailsService with Remember-me feature (PersistentTokenBasedRememberMeServices)

이미지
바로 지난 글( https://infondgndg91.blogspot.com/2020/06/spring-security-userdetailsservice-with.html )에서, 스프링 시큐리티에서 TokenBasedRememberMeServices 를 이용한 토큰 기반 Remember-Me 기능에 대해 알아보았다. 이번글에서는, PersistentTokenBasedRememberMeServices 를 이용한 영구 토큰 기반 Remember-Me 에 대해서 정리해보려고 한다. 먼저 영구 토큰 기반 Remember-Me 기능을 사용하기 위해선 말 그대로 토큰을 저장할 저장소가 필요하다. 나의 경우 MariaDB 를 사용했다. Persistent Token Based 는 Token Based 와 다르게 시그니처를 검증하지 않는다. 대신, 토큰 저장소에 일한 토큰이 존재하는지 확인한다. Persistent Token Based Cookie 는 아래와 같은 요소를 포함한다. 시리즈 식별자 (Series Identifier) : 사용자의 초기 로그인을 식별하며, 사용자가 세션에 자동으로 로그인될 때마다 값이 항상 동일하다 . 토큰 값 : 사용자가 Remember-Me 기능을 사용해 인증될 때마다 변경되는 고유한 값이다. 아래 다이어그램을 보면, Remember-Me 쿠키가 전송되면, 스프링 시큐리티는 전송된 쿠키의 시리즈 식별자를 통해서, PersistentTokenRepository 에서 예상되는 토큰값을 찾는다. 찾은 토큰의 값과 전송된 쿠키의 값을 비교하여 일치여부를 통해 인증을 한다. 사용자가 전송한 시리즈 식별자와 일치하는 값이 데이터베이스에 존재하지만 토큰 값이 일치하지 않는 경우 누군가가 Remember-Me 쿠키를 도용하고 있다고 간주할 수 있다. 해당 경우, 스프링 시큐리티는 관련된 Remember-Me 토큰을 폐기하고 사용자에게 해당 세션의 탈취 가능성을 경고한다. 이 경우 스프링 시큐리티는 관련된 모든 세션을...

Spring Security - UserDetailsService with Remember-me feature (TokenBasedRememberMeServices)

이미지
여러가지 서비스를 이용하다보면, 자동 로그인하기라는 체크 박스를 기본적으로 확인할 수 있다. 스프링 시큐리티에서 지원하는 Remember-me 라는 기능이 바로 그 기능이다. 웹사이트를 자주 방문하는 사용자에게 편리한 기능이다. 사용자가 웹 브라우저를 종료한 후에도 사용자의 웹 브라우저에 Remember-Me 쿠키를 저장함으로써 재방문 시 사용자를 기억하는 기능이다. 이는 사용자가 사용자명이나 패스워드를 다시 입력할 필요가 없다. 스프링 시큐리티 Remember-Me 기능에는 두 가지가 있다. 토큰 기반의 Remember-Me 기능으로, 암호화 시그니처 에 의존한다. (TokenBasedRememberMeServices) 영구 토큰 (Persistent Token) 기반 Remember-Me 기능이며, 데이터베이스 (datastore) 가 필요하다. (PersistentTokenBasedRememberMeServices) 먼저, 토큰 기반 Remember-Me 기능을 살펴보자. 아래의 로그인 화면과 같이, login.html 에서 Remember me 체크 박스를 만들어준다. 그리고 name attribute 설정을 해준다. spring security remember-me 기능의 default parameter 는 "remember-me" 이다. 물론 다르게 설정이 가능하다. 아래는 시큐리티 설정이다. HttpSecurity 에 rememberMe() 와 key() tokenValiditySeconds() 메서드를 통해 설정한다. key() -> Remember-Me 쿠키의 시그니처 생성 시 사용되는 고유한 키를 정의한다. 애플리케이션의 고유 이름을 포함한 최소 36자 길이의 문자열을 사용할 것을 추천한다. tokenValiditySeconds -> Remember-Me 쿠키의 만료 시간을 설정한다. -1 로 설정한다면, 2주를 의미한다....

Spring Security - In-Memory Authentication Warm-up

이미지
스프링 시큐리티는 모두들 러닝 커브가 높다는 것을 알고있다. 나 또한 그동안 스프링 시큐리티를 가볍게만 사용해보았고, 여러가지 지원되는 기술들을 면밀하게 장단점을 알고 쓰질 못했다. 스프링 진영에서 인증, 권한을 포함한 보안과 관련된 프레임워크는 단연 시큐리티 만한게 없다고 생각해왔고, 평판도 익히 들었다. 그동안 미루어왔던 시큐리티 학습을 시작해보려고 한다. 아래 책을 따라가면서, 실습을 해 볼 예정이다. 책의 버전과 현재 버전이 일치하지 않는 부분도 있고, 그냥 내가 만들고 싶은걸 만들면서 배우고 싶은 생각도 있어서 예제를 그대로 따라가지 않고 시큐리티를 실습해 볼 예정이다. http://www.acornpub.co.kr/book/spring-security-3e 우선, 책 첫 부분에 나오는 초기 세팅 및 inMemoryAuthentication 의 예제이다. spring boot 버전은 2.3.0.RELEASE 이며, spring security 버전은 5.3.2.RELEASE 이다. 아래에서 확인이 가능하다. MVC 구조에서 간단하게 진행하기 때문에, web 을 추가했고 또한 thymeleaf 템플릿 엔진을 사용할 것이다. jpa 와 h2 는 추후에 jdbc 기반 인증을 하기 위해서 미리 넣어두었다. lombok 과 devtools 는 애용하기 때문에 집어넣었다. 그렇다면, 본론으로 넘어가서 Security 설정을 해보자. WebSecurityConfigurerAdapter 를 상속 받아 configure 메서드를 재정의하면 된다. configure(AuthenticationManagerBulider) 메서드에서 AuthenticationManagerBuilder 객체는 스프링 시큐리티가 사용자를 인증하는 방법을 설정한다. 아래의 경우, 인메모리 데이터 저장소를 이용해 사용자명과 패스워드를 비교한다. 인메모리 데이터 저장소에 2개의 2개의 계정을 물고 있으며, 해당 2개의 계정만...