isAnnonymous()
와 isAuthenticated()
로 구분하여 사용동시세션
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
SessionManagementFilter 먼저 이전 사용자 세션 만료 정책을 설정한 후 session.expireNow()
정책에 따라
ConcurrentSessionFilter는 매 요청마다 세션이 만료되었는지 확인한다. 확인후 로그아웃 그리고 오류페이지
session.isExpired() == true
이미 이전 사용자가 있으면 SessionManagementFilter 가 expiredNow()를 해서 이전 사용자 세션을 만료 시킨다.
이전 사용자가 요청을 시도하면 ConcurrentSessionFilter 가 session.isExpired() 가 동작하여 로그아웃 시킴
http.antMatchers(”/user/**”).hasRole(”USER”)
@PreAuthorize(”hasRole(’USER’)”)
선언적 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(); // 나머지 요청은 인증 처리
표현식
@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();
}
FilterSecurityIntercepter
: 제일 마지막에 호출되는 클래스 이자식이 exception을 일으킴, 이 인터셉터 앞에있는 것이 ExceptionTranslationFilter
이다. 이것이 try catch 문으로 인터셉터를 감싸고 있어서 인터셉터에서 예외를 던지면 필터가 잡는다**ExceptionTranslationFilter**
AuthenticationException
AutheticationEntryPoint
호출AutheticationEntryPoint
를 호출해서 로그인 페이지로 이동하게 만들고 요청 전에 정보, 헤더값들을 세션에 담아놓고 필요할때 가져다 쓴다AccessDeniedExecption
AccessDeniedHandler
인터페이스를 구현한 곳 에서 예외 처리하도록 제공FilterSecurityIntercepter
에서 인가 예외 발생 ( 왜냐면 인증을 받지 않는 유저는 annonymous(익명사용자, 리멤버미 사용자)임 )AccessDeniedExecption
에서 Handler로 가야되지만 익명사용자나 리멤버미 사용자는AuthenticationException
간다.AuthenticationException
에서 Security Context에 null로 초기화 시키고 AutheticationEntryPoint
로 가서 login 페이지로 가게 한다