Spring Security는 스프링 기반의 애플리케이션의 보안을 담당하는 스프링 하위 프레임워크입니다.
주로 서블릿 필터와 이로 구성된 필터 체인으로 위임 모델을 사용하는데요. 보안에 관련돼서 많은 옵션을 제공해 주기 때문에 개발자 입장에서 보안 관련 로직을 작성하지 않도록 도와줍니다.
보안 관련된 용어
Principal : 접근 주체 - 보호된 리소스에 접근하는 유저를 말합니다.
Authenticate : 인증 - 로그인과 같이 자신을 증명하기 위함입니다.
Authorize : 인가 - 인증된 유저가 해당되는 리소스에 접근할 수 있는 권한이 있는지 검사합니다.
spring security는 세션을 이용합니다.
spring에서 session을 이용할 경우 요청이 왔을 때 고유 sessionKey를 발급해 유저에게 쿠키에 key를 담아 보내는 방식입니다. 다시 요청이 들어온 경우 session 저장소에 key를 통해 접근하여 해당 정보를 확인하게 되죠.

securiy의 실행 방식은
1. 유저가 요청을 보냅니다.
2. DispacherServlet이 요청을 받기 전 AuthenticationFilter가 그 정보를 받아 DB까지 들어가 인증을 합니다.
3. 만약 DB에 존재하는 유저의 요청이라면 UserDetails로 꺼내서 해당 유저의 session을 생성합니다.
4. spring security의 인메모리 세션 저장소인 SecurityContextHolder에 저장하게 됩니다.
5. 유저에게 SessionId를 담은 쿠키를 전송하며 요청된 응답을 전송해줍니다.
6. 이후 요청에서는 쿠키의 sessionId를 확인해 유효할 시 인증을 해줍니다.
모든 접근 주체는 Authentication을 생성하는데요 이 객체들을 SecurityContext에 보관됩니다.
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; }
유저의 요청을 AuthenticationFilter에서 Authentication 객체로 변환해 AuthenticationManager(ProviderManager)에게 넘겨주고, AuthenticationProvider(DaoAuthenticationProvider)가 실제 인증을 한 이후에 인증이 완료되면 Authentication객체를 반환해준다.
AuthenticationManager의 구현체인 ProviderManager을 spring security에서 제공해주는데
ProviderManager 친구가 DB에 접근해서 Authentication객체를 반환해줍니다. 실패 시 예외를 던집니다.
인증과 관련된 모든 예외는 AuthenticationException을 상속합니다.
이 클래스는 두 개의 멤버 필드를 가지고 있습니다.
authentication : 인증 됐을 때 주었던 Authentication객체를 저장합니다.
extranInfomation : 인증 예외 관련 부가 정보를 저장합니다. 실패 시 유저의 정보를 가지고 있는 것이죠
spring securiy를 사용하기 위해 의존성을 추가해주어야 합니다.
<!-- Properties --> <security.version>4.2.7.RELEASE</security.version>
<!-- Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${security.version}</version> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${security.version}</version>
</dependency>
AuthenticationManagerBuilder는 스프링 시큐리티의 인증에 대한 지원을 설정하는 몇 가지 메서드를 가지고 있다.
inMemoryAuthentication() 메소드로 활성화 및 설정이 가능하고 선택적으로 인메모리 사용자 저장소에 값을 채울 수 있다.
데이터베이스 테이블로 인증하기
스프링 시큐리티에서 JDBC 지원 사용자 저장소에서 인증하기 위해 jdbcAuthentication() 메서드를 사용한다.
기본 SQL 쿼리들을 자체적으로 디자인한 쿼리로 대체할 때, 쿼리들의 기본 조건들을 충실히 지켜주는 것이 매우 중요하다.
모든 쿼리들은 사용자명을 유일한 인자로 사용한다.
인증 쿼리에서는 사용자명, 암호, 활성화 여부를 선택한다.
권한 쿼리는 사용자명과 사용자명과 부여받은 권한으로 되어 있는 열을 선택한다.
부호화된 암호로 작업하기
사용자 암호가 데이터베이스에 저장될 때 암호를 부호화하지 않으면 문제가 될 수 있다.
이런 문제를 해결하기 위해 passwordEncoder() 메서드를 호출하여 암호에 적용할 보호 화기(encoder)를 명시할 수 있다.
스프링 시큐리티의 암호화 모듈은 다음 세 가지의 구현들을 포함한다.
- BCryptPasswordEncoder
- NoOpPasswordEncoder
- StandardPasswordEncoder
package com.farm.web.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private DataSource dataSource;
@Override //인증 url 설정
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/adsf").hasRole("ADMIN") //해당 url에 해당 역할자만 들어와야함.
.antMatchers("/seller/asdfdsaf").hasAnyRole("SELLER", "ADMIN")
.antMatchers("/member/home").authenticated() //인증이되면 home갈 수 있게 해줌.
// /admin/ 모든 하위 경로에 ADMIN이라는 역할을 갖고있는애한테 인증을 허가한다.
.and()
.formLogin() //우리가 만든 로그인 페이지로 넘기기
.loginPage("/member/login") //GET URL (URL에 보이는 로그인 경로)
//.loginProcessingUrl("/member/login") //POST URL
.defaultSuccessUrl("/index") //로그인이 성공하면 index로 넘김
//.successHandler(successHandler) //로그인 성공하면, 되는 로직 괄호안은 넘길 url쓰면됨
//.failureHandler(authenticationFailureHandler) //로그인 실패하면, 되는 로직 괄호안은 넘길 url쓰면됨
// .successHandler(new NewlectureAuthenticationSuccessHandler())
.and()
.logout() //로그아웃 설정
.logoutUrl("/member/logout") //로그아웃 경로 (URL에 보이는 로그아웃 경로)
.logoutSuccessUrl("/index") // 로그아웃 되면 넘어갈 경로
.invalidateHttpSession(true)//사용자 로그아웃시 세션 초기화
.and()
.csrf() //csrf무효화 시키는 방법
.disable();
}
@Override //사용자의 권한정보, 계정정보를 설정
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth //DB에 있는 내용 사용
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select uid id, pwd password, 1 enabled from Member where uid=?")//endabled 사용자가 활성화 됬냐 (휴면계정같은 느낌)
.authoritiesByUsernameQuery("SELECT uid id, 'ROLE_ADMIN' roleId FROM Member where uid=?") //사용자 권한을 작성하는 테이블
.passwordEncoder(new BCryptPasswordEncoder()) //DB에 암호화된 비번을 비교하는 것
;
}
}
--수정중--
'Spring|Spring-boot' 카테고리의 다른 글
| Lombok (0) | 2020.08.03 |
|---|---|
| [Spring] Interceptor , ArgumentResolver (0) | 2020.07.20 |
| [Spring] Spring MVC Session (0) | 2020.07.20 |
| [Spring] MessageConverter (0) | 2020.07.17 |
| 레이어드 아키텍쳐 (0) | 2020.07.17 |
댓글