일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 제네릭 와일드 카드
- yield
- System.err
- 바운디드 타입
- 프리미티브 타입
- auto.create.topics.enable
- 로컬 클래스
- 정렬
- 자바할래
- Study Halle
- 익명 클래스
- junit 5
- 자바스터디
- 제네릭 타입
- github api
- Switch Expressions
- System.out
- 항해99
- 브릿지 메소드
- 람다식
- 스파르타코딩클럽
- 접근지시자
- docker
- throwable
- 합병 정렬
- raw 타입
- annotation processor
- 함수형 인터페이스
- System.in
- 상속
Archives
- Today
- Total
코딩하는 털보
21.10.02 TIL 본문
나의 항해 블로그에 계정 회원가입/로그인/로그아웃 기능을 추가하려고 한다.
JWT를 사용해서 인증하는 것을 해보고싶긴하지만, 일단 세션 방식의 인증과 시간이 남는다면 소셜 로그인 기능까지만 추가할 예정이다.
회원 가입
계정 클래스 만들기
@Entity
@Getter
@NoArgsConstructor
public class Account extends Timestamped{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false)
private String username;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String role = "ROLE_USER";
private Account(AccountRequestDto requestDto) {
this.username = requestDto.getUsername();
this.password = requestDto.getPassword();
}
public static Account from(AccountRequestDto requestDto) {
return new Account(requestDto);
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", username='" + username + '\'' +
'}';
}
}
SecurityConfig를 수정했다.
/account/** 는 CSRF 방어를 하지 않는다.
인증하지 않고도 로그인/회원가입 페이지는 확인 할 수 있도록 했다.
인증하지 않으면 /articles/** 는 GET 만 허용한다.
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/", "/images/**", "/css/**", "/account/**").permitAll() .antMatchers(HttpMethod.GET, "/articles/**").permitAll() .anyRequest().authenticated() .and() .csrf().ignoringAntMatchers("/account/**") .and() .formLogin() .loginPage("/account/login") .loginProcessingUrl("/account/login") .defaultSuccessUrl("/", true) .failureUrl("/account/login?error") .permitAll() .and() .logout().logoutUrl("/account/logout") .and() .exceptionHandling() .accessDeniedPage("/forbidden.html"); }
}
회원가입 컨트롤러
@Controller
@RequestMapping("/account")
@RequiredArgsConstructor
public class AccountController {
private final AccountService accountService;
@GetMapping("/register")
public String registerPage() {
return "register";
}
@PostMapping("/register")
public String register(@RequestBody AccountRequestDto requestDto) {
accountService.registerAccount(requestDto);
return "redirect:/login";
}
@GetMapping("/login")
public String loginPage() {
return "login";
}
}
암호화한 패스워드로 저장하기.
@Service
@RequiredArgsConstructor
public class AccountService {
private final AccountRepository accountRepository;
private final PasswordEncoder passwordEncoder;
public void registerAccount(AccountRequestDto requestDto) {
if ( accountRepository.findByUsername(requestDto.getUsername()).isPresent() ) {
throw new UsernameExistException("중복된 닉네임입니다.");
}
String password = requestDto.getPassword();
String encodedPassword = passwordEncoder.encode(password);
requestDto.setPassword(encodedPassword);
accountRepository.save(Account.from(requestDto));
}
}
메인 페이지에 유저 정보를 모델로 담아서 보내준다.
@GetMapping("/")
public String home(@AuthenticationPrincipal UserDetails userDetails, Model model) {
if ( userDetails != null ) {
String username = userDetails.getUsername();
model.addAttribute("username", username);
}
return "index";
}
로그인
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private final AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByUsername(username).orElseThrow(
() -> new UsernameNotFoundException("유저가 존재하지 않습니다.")
);
return UserDetailsImpl.of(account);
}
}
public class UserDetailsImpl implements UserDetails {
private final Account account;
private UserDetailsImpl(Account account) {
this.account = account;
}
public static UserDetailsImpl of(Account account) {
return new UserDetailsImpl(account);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return account.getPassword();
}
@Override
public String getUsername() {
return account.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
앞으로의 과제
- 소셜 로그인 기능
- 3주차 강의 듣기
- 테스트 코드 작성 및 리팩터링
- 4,5 주차 강의 듣기
- 나머지 과제 진행하기
Comments