iframe
http.headers().frameOptions().disable(); // iframe 허용안함.
What is an inline frame (iframe)?
Learn about iframes, inline frames, an HTML element that loads another HTML page within the document. See how it works, is used and pluses/minuses.
www.techtarget.com
- iframe이란 inline frame의 약자
- iframe 요소를 이용하면 해당 웹 페이지 안에 어떠한 제한 없이 또 다른 하나의 웹 페이지를 삽입할 수 있다.
- 여기서 http.headers().frameOptions().disable() -> 이 iframe 요소를 허용하지 않겠다는 뜻!
CSRF
http.csrf().disable();
- https://www.youtube.com/watch?v=nzoUgKPwn_A
- 설명을 듣는 것보다 이렇게 해킹 기법을 실제로 보게 되니깐 더 이해가 가는 느낌이다.
- CSRF(교차 사이트 요청 위조)는 인증된 사용자가 현재 인증된 웹 애플리케이션에 강제로 요청을 제출하도록 하는 공격이다.
- CSRF 공격은 웹 애플리케이션이 인증된 사용자에 대해 가지고 있는 신뢰를 악용한다 (반대로 크로스 사이트 스크립팅(XSS) 공격은 사용자가 특정 웹 애플리케이션에 대해 갖고 있는 신뢰를 악용한다)
- 웹 애플리케이션이 개별 사용자가 생성한 요청과 사용자의 동의 없이 생성한 요청을 구분할 수 없는 경우 CSRF 공격은 웹 애플리케이션의 취약점을 악용한다.
- 여기서 csrf()설정을 disable 해둔 점은 postman을 사용할 수 없기 때문에 disable 설정을 넣어주었다.
CORS
http.cors().configurationSource(configurationSource());
public CorsConfigurationSource configurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*"); // GET, POST, PUT, DELETE (Javascript 요청 허용)
configuration.addAllowedOriginPattern("*"); // 모든 IP 주소 허용 (프론트 엔드 IP만 허용 react)
configuration.setAllowCredentials(true); // 클라이언트에서 쿠키 요청 허용
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
교차 출처 리소스 공유 (CORS) - HTTP | MDN
교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라
developer.mozilla.org
SessionCreationPolicy
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
SessionCreationPolicy (Spring Security 4.2.5.RELEASE API)
valueOf public static SessionCreationPolicy valueOf(java.lang.String name) Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace
docs.spring.io
- SessionCreationPolicy.ALWAYS: Always create an HttpSession: 항상 세션을 생성
- SessionCreationPolicy.IF_REQUIRED: Spring Security will only create an HttpSession if required: Spring Security는 필요한 경우에만 HttpSession을 생성
- SessionCreationPolicy.NEVER: Spring Security will never create an HttpSession, but will use the HttpSession if it already exists: Spring Security는 HttpSession을 생성하지 않으나, 이미 존재하는 경우 HttpSession을 사용한다.
- SessionCreationPolicy.STATELESS: Spring Security will never create an HttpSession and it will never use it to obtain the SecurityContext: Spring Security는 절대로 HttpSession을 생성하지 않으며, 이를 사용하여 SecurityContext를 가져오지도 않는다.
- SecurityContext: Interface defining the minimum security information associated with the current thread of execution.
- 현재 실행 스레드와 관련된 최소 보안 정보를 정의하는 인터페이스를 의미
formLogin()
http.formLogin().disable();
- formLogin을 사용하지 않고 JWT방식을 사용하기 때문에 disable() 설정 추가
- https://tech.toktokhan.dev/2021/04/30/JWT/
- https://youtu.be/1QiOXWEbqYQ
- Authentication: 쉽게 말해서 로그인. 내가 이 사이트에 가입된 사용자임을 아이디와 패스워드를 통해 인증을 받음
- Authorization: 인증을 받은 사용자가 이후 서비스의 여러 기능들을 사용할 때 서버가 로그인을 한 사용자라는 것을 알아보고 허가해주는 것
- JWT는 인가 Authorization에 연관된 기술
- 어떤 사이트나 서비스에 사용자가 로그인해있다는 사실을 서버가 인지할 수 있도록 하는 방법이 뭐가 있을까?
- 세션방식: 사용자가 로그인에 성공하면, 서버는 세션을 발행, 반으로 나눠서 반쪽은 사용자의 브라우저로 보내고, 다른 반쪽은 메모리(or 하드디스크, DB)에 올려놓는 것.
- 사용자의 브라우저(크롬, 엣지): 받은 반쪽을 Session ID란 이름의 쿠키로 저장(쿠키: 브라우저에 저장되는 정보). 로그인한 서비스에 요청을 보낼때마다 이 Session ID란 이름의 쿠키를 실어보낸다. 요청에 Session ID가 같이 넘어오면 서버는 메모리(DISK, DB)에 짝이 있는지 찾아서 있으면 인가(Authorization)을 해주는 것.
- Session ID를 사용해서 어떤 사용자가 서버에 로그인 되어있음이 지속되는 상태: "세션"이라고 함
- 서버가 재부팅하게 되면 메모리가 휘발되면서 모든 사용자는 로그인이 풀리게 된다.
- 서버가 복잡한 구성과 환경에서 어떤 상태를 기억해야 된다는게 설계하기 어려운 것.
- 부담이 많은 이 인가를 구현하기 위해 고안된 게 "토큰방식" JWT
- JWT: JSON Web Token
- 토큰방식이란?
- JWT를 사용하는 서비스에는 사용자가 로그인을 하면 토큰이라는 걸 넘겨준다.
- 세션은 반으로 나눠서 주었는데, 여기서는 그냥 토큰 전체를 주는 형식이다. -> 서버가 기억하고 있지 않는다
- 토큰 -> 인코딩 또는 암호화된 3가지 데이터를 이어붙인 것. header(헤더), payload(페이로드), verify signature(서명)로 구분
- 페이로드: Base64로 디코딩해보면 JSON형식으로 여러 정보들이 들어 있음. 토큰을 누가 누구에게 발급했는지, 이 토큰이 언제까지 유효한지, 서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용(사용자의 닉네임, 서비스상의 레벨, 관리자 여부) 등을 서비스 측에서 원하는 대로 담을 수 있음. -> 이런 데이터를 Claim이라고 함.
- 헤더: 디코딩하면 두 가지 정보가 담겨 있음.
- type: 토큰의 타입 JWT를 의미
- alg: 알고리즘의 약자 -> 서명(verify signature)를 만드는데 사용될 알고리즘이 지정(HS256 등 여러 암호화 방식 중 하나를 지정)
- header와 payload, 서버에 감춰놓은 비밀 이 셋을 alg 암호화 알고리즘에 넣고 돌리면 서명값(verify signature)가 나오는 것
- 서버는 header와 payload의 값을 서버의 비밀 키와 함께 돌려봐서 계산된 결과값이 서명값(verify signature)과 일치하는 지 확인.
- 서명 값(verify signature)과 계산이 일치하고 유효기간도 지나지 않았다면 사용자는 로그인 된 회원으로서 인가를 받는 것
- JWT가 좋은가?
- 세션처럼 STATEFUL해서, 모든 사용자들의 상태를 기억하고 있다는 건, 기억하고 있는 대상의 상태들을 언제든 제어할 수 있다는 의미.
- 예) 한 기기에만 로그인 가능한 서비스를 만들려는 경우
- 세션 방식에서는 서버가 가지고 있는 세션을 제거하면 간단하게 제어가능. JWT에서는 이런 작업이 불가능
- 이미 준 토큰을 회수할 수 없고, 서버가 토큰을 추적하고 있는 것도 아니기 때문
- 혹은 토큰이 탈취당한 경우, 이 토큰을 무효화할 방법도 없는 것.
- 그래서 실 서비스에서 JWT로만 인가를 구현하는 곳은 그렇게 많지 않음.
httpBasic()
http.httpBasic().disable();
- 브라우저가 팝업창을 이용해서 사용자의 인증을 진행하는 것을 disable 해두었다.
http.authorizeHttpRequests()
http.authorizeHttpRequests()
.antMatchers("/api/s/**").authenticated()
.antMatchers("/api/admin/**").hasRole("" + UserEnum.ADMIN) // 최근 공식문서에서는 ROLE_ 안붙여도 됨
.anyRequest().permitAll();
- Authorize: 인가
- /api/s/** -> 인증된 사용자만
- /api/admin/** -> 여기로 오는 요청은 관리자 권한을 가진 사용자만 인가한다.
'CS지식들 > 공부공부' 카테고리의 다른 글
회원 가입 로직 구현 (1) | 2023.03.09 |
---|---|
인증(Authentication) 관련 Exception을 제어하는 기능 구현 (0) | 2023.03.09 |
동시성 문제 (3) (0) | 2022.12.19 |
동시성 문제 (2) (0) | 2022.12.19 |
동시성 문제 (1) (0) | 2022.12.18 |