스프링 부트 기초 - 9(SpringSecurity 다시 보기)
스프링 시큐리티 설정
▶ SecurityConfig
@Configuration // 빈등록(IoC관리)
@EnableWebSecurity // 시큐리티 필터가 등록이 된다.
@EnableGlobalMethodSecurity(prePostEnabled = true) // 특정 주소로 접근을 하면 권한 및 인증을 미리 체크 하겠다는 뜻
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // csrf 토큰 비활성화(테스트시 걸우두는게 좋음)
.authorizeRequests()
.antMatchers("/", "/auth/**", "/js/**", "/css/**", "/image/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/auth/loginForm")
.loginProcessingUrl("/auth/loginProc") // 스프링 시큐리티가 해당 주소로 요청오는 로그인을 가로챈다. 대신 로그인 해준다.
.defaultSuccessUrl("/"); // 정상적으로 로그인이 되면 여기로 이동
}
}
비밀번호 해쉬화 하기(암호화)
▶ SecurityConfig
@Configuration // 빈등록(IoC관리)
@EnableWebSecurity // 시큐리티 필터가 등록이 된다.
@EnableGlobalMethodSecurity(prePostEnabled = true) // 특정 주소로 접근을 하면 권한 및 인증을 미리 체크 하겠다는 뜻
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Bean
public BCryptPasswordEncoder endcodePWD() {
return new BCryptPasswordEncoder();
}
}
- BCryptPasswordEncoder 객체를 Bean 으로 등록
▶ UserService
@Autowired
private BCryptPasswordEncoder encoder;
@Transactional
public void 회원가입(User user) {
String rawPassword = user.getPassword(); // 1234 원래 비밀번호
String encPassword = encoder.encode(rawPassword); // 해쉬화
user.setPassword(encPassword); // 해쉬화 된 패스워드로 셋
user.setRole(RoleType.USER);
userRepository.save(user);
}
스프링 시큐리티로 로그인 하기
▶ SecurityConfig
@Configuration // 빈등록(IoC관리)
@EnableWebSecurity // 시큐리티 필터가 등록이 된다.
@EnableGlobalMethodSecurity(prePostEnabled = true) // 특정 주소로 접근을 하면 권한 및 인증을 미리 체크 하겠다는 뜻
public class SecurityConfig extends WebSecurityConfigurerAdapter{
// 시큐리티가 대신 로그인해주는데 password를 가로채기 하는데
// 해당 password가 뭘로 해쉬가 되어 회원가입이 되었는지 알아야
// 같은 해쉬로 암호화해서 DB에 있는 해쉬랑 비교할 수 있음.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(principalDetailService).passwordEncoder(endcodePWD());
}
@Bean
public BCryptPasswordEncoder endcodePWD() {
return new BCryptPasswordEncoder();
}
}
▶ PrincipalDetail
@Getter
public class PrincipalDetail implements UserDetails{
private User user; // 컴포지션
public PrincipalDetail(User user) {
this.user = user;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
// 계정이 만료되지 않았는지 리턴한다.(true : 만료 안됨)
@Override
public boolean isAccountNonExpired() {
return true;
}
// 계정이 잠겨있지 않았는지 리턴한다.(true : 잠기지 않음)
@Override
public boolean isAccountNonLocked() {
return true;
}
// 비밀번호가 만료되지 않았는지 리턴. (true : 만료안됨)
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
// 계정이 활성화(사용가능)인지 리턴한다. (true : 활성화)
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
// 계정이 갖고있는 권한 목록을 리턴한다. (권한이 여러개 있을 수 있어서 루프를 돌아야 하는데 우리는 한개만)
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collectors = new ArrayList<>();
collectors.add(() -> {return "ROLE_" + user.getRole();});
// collectors.add(new GrantedAuthority () {
// public String getAuthority() {
// return "ROLE_" + user.getRole(); // ROLE_USER -> ROLE 꼭 붙여주기
// }
// });
return collectors;
}
}
UserDetails를 implements 하여 사용한다
UserDetails
Security에서 사용자의 정보를 담는 인터페이스가 UserDetails 인터페이스이다.
이 인터페이스를 구현하게 되면 이제 Security 인증, 인가 관련 작업에서 우리가 구현한 인터페이스를 기준으로 작업하게 될 것이다.
스프링 시큐리티(현재 사용자 조회)
@AuthenticationPrincipal 어노테이션을 활용해 현재의 로그인 정보를 얻어 온다
@PostMapping(value = "/api/board")
public ResponseDto<Integer> save(@RequestBody Board board, @AuthenticationPrincipal PrincipalDetail principal) {// title, content
boardService.글쓰기(board, principal.getUser()); // principal.getUser()는 현재 세션의 아이디를 의미
return new ResponseDto<Integer>(HttpStatus.OK.value(),1);
}
Leave a comment