-
[스프링] 시큐리티 - 2 (DB 연동)Spring 2020. 10. 5. 19:02
- 참고 : 인프런 >>스프링 시큐리티 (백기선 강의)
- 참고 : github
[준비]
1. JPA 의존성 추가
2. H2 Database 의존성 추가
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency>
"UserDetailsService" ?
- 스프링 시큐리티에서 제공
- 스프링 시큐리티에서 DAO(Data access object) 구현체를 통해 User의 정보를 가져와 "UserDetails" 타입으로 캐스팅
ex) 예제
1. 유저 정보를 DB에서 찾는다. >> "user"
Account account = accountRepository.findByUsername(username);
2. "user" >> UserDetail로 변경
return User.builder() .username(account.getUsername()) .password(account.getPassword()) .roles(account.getRole()) .build();
[예제]
1. Account (User 정보를 담는 Table, Entity) 생성
@Entity @Getter @Setter public class Account { @Id @GeneratedValue private Long id; @Column(unique = true) private String username; private String password; private String role; }
2.AccountRepository 생성
public interface AccountRepository extends JpaRepository<Account,Long> { Account findByUsername(String username); }
3. AccountService 생성 >> "UserDetailService" 구현체
@Service @RequiredArgsConstructor public class AccountService implements UserDetailsService { private final AccountRepository accountRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Account account = accountRepository.findByUsername(username); if(account == null){ throw new UsernameNotFoundException(username); } return User.builder() .username(account.getUsername()) .password(account.getPassword()) .roles(account.getRole()) .build(); } public Account createNew(Account account) { account.setPassword("{noop}" + account.getPassword()); return accountRepository.save(account); } }
4. 유저 생성 API 추가
@RestController @RequiredArgsConstructor public class AccountController { private final AccountService accountService; @GetMapping("/account/{role}/{username}/{password}") public Account createAccount(@ModelAttribute Account account) { return accountService.createNew(account); } }
Security config
@Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { private final AccountService accountService; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .mvcMatchers("/","/info","/account/**").permitAll() .mvcMatchers("/admin").hasRole("ADMIN") .anyRequest().authenticated(); http.formLogin(); http.httpBasic(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(accountService); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
[시나리오]
1. 유저생성
- > GET: localhost:8080/account/ADMIN/admin/123
2. 로그인
admin / 123
3. "/admin" 접근
패스워드 인코더 추가
-> "{noop}"를 없앤다.
- 비밀번호는 반드시 인코딩해서 저장
- 다양한 해싱 전략의 패스워드를 지원
1. 패스워드 인코더 추가
@Bean public PasswordEncoder passwordEncoder(){ return PasswordEncoderFactories.createDelegatingPasswordEncoder(); }
2. 인코딩
public Account createNew(Account account) { account.setPassword(passwordEncoder.encode(account.getPassword())); return accountRepository.save(account); }
'Spring' 카테고리의 다른 글
[스프링] 시큐리티 -4 (SecurityContextHolder) (0) 2020.10.09 [스프링] 시큐리티 -3 (Test) (0) 2020.10.09 [스프링] 시큐리티 - 1 (인메모리 유저) (0) 2020.10.05 [스프링] @Cacheable (0) 2020.09.15 [스프링배치] 개념 (0) 2020.06.14 댓글