티스토리 뷰
Spring Security
로그인하여 세션에 정보를 저장하고, 유저 권한에 따른 URI 접근까지 Spring Security를 이용하면 간편하게 구현 할 수있다.. 라고 배웠지만, 공부하기가 너무 어렵다. 이런저런 예제를 따라해보기도 했고, Spring Boot와 Spring의 시큐리티 설정이 얼마나 다른지도 몰라 예제를 찾아보는 것도 힘들었다. 2일간 삽질하여 얼추 원하는 방향으로 구현 할 수 있었다. (막상 완성된 예제를 보니 아주 어렵지는 않았지만 삽질의 주된 원인은 어떤 곳이 문제인지 알 수가 없었기 때문이었다.) 시큐리티는 개발하면서 지속적으로 공부를 해봐야 정교하게 구현 할 수 있을 것 같다. 현재까지 구현한 시큐리티는 아래와 같다.
WebSecurityConfigureAdapter
WebSecurityConfigureAdapter을 상속받은 시큐리티 설정 클래스를 선언한다. 이 클래스에서는 유저 권한에 따른 URI 접근을 설정한다. 예를들어 /admin 으로 시작하는 URI는 "ADMIN" 권한이 있는 유저만 접근 가능하고, 인덱스 페이지나 회원 가입 페이지는 모든 사용자가 접근 가능하다.
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resoures/**", "/static/**", "/css/**", "js/**", "/images/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/users").permitAll() //모든 사용자가 접근가능
.antMatchers("/books").hasRole("USER")
.antMatchers("/admin").hasRole("ADMIN")//ADMIN 권한이 있는경우만 접근 가능
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/session")
.loginProcessingUrl("/session")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/")
.permitAll();
}
}
Security 코어의 userdetails
스프링 코어 (org.springframework.security.core.userdetails.User)의 User 클래스를 상속받은 UserDetails 설정을 한다. 이 클래스는 필수적이진 않지만 시큐리티 코어의 User와 실제 서비스 하고 있는 User 도메인과의 차이점을 이 클래스로 상쇄시켜줄 수 있다.
public class CustomUserDetails extends User {
private String nickname; // 사람이름
private Long id;
public CustomUserDetails(String email, String password, Collection authorities) {
super(email, password, true, true, true, true, authorities);
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail(){
return super.getUsername();
}
}
UserDetailsService
UserDetailsService를 구현한 클래스를 선언한다. 이 클래스는 실제 서비스 되고 있는 회원들의 정보를 가져와서, 시큐리티가 알 수 있는 UserDetails로 변환하여 반환하는 작업을 한다.
@Component
@RequiredArgsConstructor
public class UserDetailServiceImpl implements UserDetailsService {
private final UserService userService;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userService.getUser(email);//실제 저장된 유저 정보 가져오기
if (user == null) {
throw new UsernameNotFoundException(email + " is not found");
}
Collection<grantedauthority> authorities = new ArrayList<>();
for(Role role : user.getRoles()){
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
}
//userDetails로 변환
CustomUserDetails userDetails = new CustomUserDetails(email, user.getPassword(), authorities);
userDetails.setNickname(user.getNickname());
userDetails.setId(user.getId());
return userDetails;
}
}
BCryptPasswordEncoder
BCryptPasswordEncoder클래스를 빈으로 생성한다. 이 클래스는 비밀번호를 DB상의 그대로 저장하지 않고 암호화 시켜서 저장 시켜주는 역할을 한다.
@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
return bCryptPasswordEncoder;
}
}
'Project' 카테고리의 다른 글
웹 프로젝트 PAT - 10. 부트스트랩 테마 적용하기 (0) | 2019.01.26 |
---|---|
웹 프로젝트 PAT - 09. 책 목차 정렬하기 알고리즘 (0) | 2019.01.16 |
웹 프로젝트 PAT - 07. View단 (0) | 2019.01.05 |
웹 프로젝트 PAT - 06. Domain 설계 (2) (0) | 2018.12.30 |
웹 프로젝트 PAT - 05. URL 설계 (0) | 2018.12.28 |