본문 바로가기
스프링과 JPA 기반 웹 어플리케이션 개발/1부 (개발환경, 회원가입, 로그인, 계정설정)

31. 패스워드를 잊어버렸습니다.

by Backchus 2020. 4. 22.

패스워드를 잊은 경우에는 "로그인 할 수 있는 링크"를 이메일로 전송한다.

이메일로 전송된 링크를 클릭하면 로그인 한다.

 

GET /email-login

  • 이메일을 입력할 수 있는 폼을 보여주고, 링크 전송 버튼을 제공한다.

POST /email-login

  • 입력받은 이메일에 해당하는 계정을 찾아보고, 있는 계정이면 로그인 가능한 링크를 이메일로 전송한다.
  • 이메일 전송 후, 안내 메시지를 보여준다.

GET /login-by-email

  • 토큰과 이메일을 확인한 뒤 해당 계정으로 로그인한다.

 

핸들러 작성

package me.weekbelt.studyolle.account;

@RequiredArgsConstructor
@Controller
public class AccountController {
    // 기존 코드 ......

    @GetMapping("/email-login")
    public String emailLoginForm() {
        return "account/email-login";
    }

    @PostMapping("/email-login")
    public String sendEmailLoginLink(String email, Model model, RedirectAttributes attributes) {
        Account account = accountRepository.findByEmail(email);
        if (account == null){
            model.addAttribute("error", "유효한 이메일 주소가 아닙니다.");
            return "account/email-login";
        }

        if(!account.canSendConfirmEmail()) {
            model.addAttribute("error", "이메일 로그인은 1시간 뒤에 사용할 수 있습니다.");
            return "account/email-login";
        }

        accountService.sendLoginLink(account);
        attributes.addFlashAttribute("message", "이메일 인증 메일을 발송했습니다.");
        return "redirect:/email-login";
    }

    @GetMapping("/login-by-email")
    public String loginByEmail(String token, String email, Model model) {
        Account account = accountRepository.findByEmail(email);
        String view = "account/logged-in-by-email";
        if (account == null || !account.isValidToken(token)) {
            model.addAttribute("error", "로그인할 수 없습니다.");
            return view;
        }

        accountService.login(account);
        return view;
    }
}

 

이메일로 로그인을 하기위한 sendLoginLink메소드 작성

package me.weekbelt.studyolle.account;

@Transactional
@RequiredArgsConstructor
@Service
public class AccountService implements UserDetailsService {

   // 기존 코드 .......

    public void sendLoginLink(Account account) {
        account.generateEmailCheckToken();;
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setTo(account.getEmail());
        mailMessage.setSubject("스터디올래, 로그인 링크");
        mailMessage.setText("/login-by-email?token=" + account.getEmailCheckToken() +
                "&email=" + account.getEmail());
        javaMailSender.send(mailMessage);
    }
}

 

패스워드 없이 로그인하는 뷰를 요청할때 로그아웃상태이므로 인증이 필요없기때문에 SpringSecurity에서 WebSecurity설정에 account/email-login을 추가한다.

또한 이메일인증 요청 처리를 위한 /login-by-email의 접근을 추가한다.

package me.weekbelt.studyolle.config;

@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final AccountService accountService;
    private final DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // /login-by-email 추가
        http.authorizeRequests()
                .mvcMatchers("/", "/login", "/sign-up", "/check-email-token", "/login-by-email",
                        "/email-login", "/check-email-login", "/login-link").permitAll()
                .mvcMatchers(HttpMethod.GET, "/profile/*").permitAll()
                .anyRequest().authenticated();

        // 기존 코드 .......
        ;
    }

    // 기존 코드 ...........

    // static 관련 파일들은 스프링 시큐리티 적용 x
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .mvcMatchers("account/email-login")         // 추가
                .mvcMatchers("/node_modules/**")
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations());
    }
}

 

 

 

참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1/dashboard

 

인프런 - 로그인이 필요합니다

2020년 4월 21일 ~ 4월 29일 안내 글 보기 >>

www.inflearn.com