Spring Security - 정수원 3일차

8. 인증 API - AnonymousAuthenticationFilter

  • 익명사용자 인증 처리 필터
  • 익명사용자와 인증 사용자를 구분해서 처리하기 위한 용도로 사용
  • 화면에서 인증 여부를 구현할때 isAnnonymous()isAuthenticated()로 구분하여 사용
  • 인증객체를 세션에 저장하지 않는다.

9. 인증 API - 동시 세션 제어 / 세션고정보호 / 세션 정책

동시세션

  1. 최대 세션 허용 개수를 설정한다. ( 만약 1이라면 )
  2. 두 명 이상의 유저가 로그인 한다
  • 두가지 경우가 있다.
    1. 이전 사용자 세션을 만료 하는 경우
    2. 현재 사용자 인증을 실패하게 하는 경우
http
                .sessionManagement()   // 세션관리 기능 동작
                .maximumSessions(1)  // 최대 허용 가능 세션 수, -1 : 무제한
                .maxSessionsPreventsLogin(true);  // 동시 로그인 차단(현재 세션 만료)
												 // false : 기존 세션만료
				.invalidSessionUrl("/invalid") // 세션이 유효하지않을때 이동 할 페이지
				.expiredUrl("/expired");  // 세션이 만료될 경우 이동 할 페이지

세션고정보호

http
.sessionManagement()
.sessionFixation().changeSessionId() //기본값, 세션에 id를 새롭게 변경
.sessionFixation().migrateSession() // 기존에 session에 있던 정보를 새로운 session에 
									// copy하여 새롭게 만들어서 사용한다.
.sessionFixation().newSession() // 이전에 Session 값을 copy하지 않고 정말 새롭게 
								// session을 만들어서 사용 한다.
.sessionFixation().none() // 아무런 작업도 하지않음.

세션 정책

http
	.sessionManagement()
	.sessionCreationPolicy(SessionCreationPolicy.Always) // 스프링 시큐리티가 항상 세션 생성
	.sessionCreationPolicy(SessionCreationPolicy.If_Required) // 필요시 생성(기본값)
	.sessionCreationPolicy(SessionCreationPolicy.Never) // 생성하지 않지만 이미 존재하면 사용
	.sessionCreationPolicy(SessionCreationPolicy.Stateless) //생성x, 존재 x

11. 인증 API - SessionManagementFilter, ConcurrentSessionFilter

  • SessionManagementFilter 먼저 이전 사용자 세션 만료 정책을 설정한 후 session.expireNow() 정책에 따라

  • ConcurrentSessionFilter는 매 요청마다 세션이 만료되었는지 확인한다. 확인후 로그아웃 그리고 오류페이지

    • session.isExpired() == true
      • 로그아웃처리
      • 즉시 오류 페이지 응답
  • 이미 이전 사용자가 있으면 SessionManagementFilter 가 expiredNow()를 해서 이전 사용자 세션을 만료 시킨다.

  • 이전 사용자가 요청을 시도하면 ConcurrentSessionFilter 가 session.isExpired() 가 동작하여 로그아웃 시킴

12. 인가 API - 권한 설정 및 표현식

  • 선언적 방식
    • URL
      • http.antMatchers(”/user/**”).hasRole(”USER”)
    • Method
      • @PreAuthorize(”hasRole(’USER’)”)
      • public void user(){ System.out.println(”user”) }
  • 동적 방식
    • URL
    • Method

선언적 URL 방식

.antMatcher("/shop/**") // url에 접근시 인증 없으면 모든페이지 인증
.authorizeRequests()
.antMatchers("/shop/login","/shop/user/**").permitAll() //이 페이지 모든 접속 가능
.antMatchers("/shop/mypage").hasRole("USER") // 페이지 유저만 가능
.antMatchers("/shop/admin/pay").access("hasRole('ADMIN')") // ADMIN만 가능
.antMatchers("/shop/admin/**").access("hasRole('ADMIN') or hasRole('SYS')") //ADMIN or SYS
.anyRequest().authenticated(); // 나머지 요청은 인증 처리
  • 주의 : 설정시 구체적인 것이 먼저오고 큰 범위의 경로는 뒤에 와야됨, 순서대로 처리함

표현식

  • anonymous() 는 익명 사용자만 혀용 USER 사용자 불가
  • hasRole(String) : RoleUSER 가 있으면 Role 은 빼고 넣어야됨 Role을 같이 넣으면 안됨( 프리픽스X)
  • hasAuthority(String) : 프리픽스 허용
  • hasAny~~~ : 안에 있는 역할중 하나만 들어와도 허용
@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user")
									 .password("{noop}1111").roles("USER");
        auth.inMemoryAuthentication().withUser("sys")
									 .password("{noop}1111").roles("SYS","ADMIN");
        auth.inMemoryAuthentication().withUser("admin")
								     .password("{noop}1111").roles("ADMIN","USER","SYS");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .authorizeRequests()
                .antMatchers("/user").hasRole("USER")
                .antMatchers("/admin/pay").hasRole("ADMIN")
                .antMatchers("/admin/**").access("hasRole('ADMIN') or hasRole('SYS')")
                .anyRequest().authenticated();
        http
                .formLogin();

    }
  • 위에는 메모리에 역할을 부여한다. 나중에는 디비에 동적으로 한다
  • Matcher도 나중에 동적으로 ㄱㄱ

13. 인증/인가 API - 예외 처리 및 요청 캐시 필터

  • FilterSecurityIntercepter : 제일 마지막에 호출되는 클래스 이자식이 exception을 일으킴, 이 인터셉터 앞에있는 것이 ExceptionTranslationFilter 이다. 이것이 try catch 문으로 인터셉터를 감싸고 있어서 인터셉터에서 예외를 던지면 필터가 잡는다
  • **ExceptionTranslationFilter**
    • AuthenticationException
      • 인증 예외 처리
        1. AutheticationEntryPoint 호출
          • 로그인 페이지 이동, 401 오류 코드 전달 등
          • 직접 인터페이스를 구현하면 커스텀하게 처리 가능
        2. 인증 예외가 발생하기 전의 요청 정보 저장
          • user가 메인페이지 들어갈 때 로그인을 하지 않아서 거부 당하면 로그인 페이지로 이동하게된다. 이때 메인페이지를 저장하고 있다가 로그인하게 되면 바로 메인페이지로 이동 시켜줌
            • RequestCache 인터페이스 구현체가 이 역할을 한다- 사용자 요청 이전 정보를 세션에 저장, SavedRequest에서 저장한 값을 세션에 저장해준다
            • SavedRequest : 사용자가 이전에 요청 했던 request파라미터 값들, 그 당시 헤더 값들 저장 ( 실제로 값들이 저장 되는 곳 )
        3. 정리 : AutheticationEntryPoint 를 호출해서 로그인 페이지로 이동하게 만들고 요청 전에 정보, 헤더값들을 세션에 담아놓고 필요할때 가져다 쓴다
    • AccessDeniedExecption
      • 인가 예외 처리
        • AccessDeniedHandler인터페이스를 구현한 곳 에서 예외 처리하도록 제공
  1. 사용자가 인증을 받지않고 /user 자원에 접근한다 가정
  2. FilterSecurityIntercepter 에서 인가 예외 발생 ( 왜냐면 인증을 받지 않는 유저는 annonymous(익명사용자, 리멤버미 사용자)임 )
  3. AccessDeniedExecption 에서 Handler로 가야되지만 익명사용자나 리멤버미 사용자는AuthenticationException 간다.
  4. 쉽게 인증 예외로 간다
  5. AuthenticationException 에서 Security Context에 null로 초기화 시키고 AutheticationEntryPoint 로 가서 login 페이지로 가게 한다
  6. 이때 그전에 정보를 DefaultSavedRequest 객체안에 저장을 하고 Session에 저장한다. 이 역할을 HttpSessionRequestCache 가 하게 된다
  7. 다음 사용자는 인증은 받았는데 권한이 없는 경우 인가 예외 발동, 순서대로 간다음 보통 /denied로 가게됨.

좋은 웹페이지 즐겨찾기