암호화를 마지막에 하려고 남겨놨다가 중간에 암호화를 하였다.
우선 암호화가 필요한 코드들을 정리했다.
- 회원가입
- 회원탈퇴
- 비밀번호 변경
암호화를 사용하려면
<pom.xml 에 의존성 추가>
<!-- spring security에서 제공하는 암호화 모듈 의존성 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<@configuration을 만든다!! 제일먼저 해야할일!!!> - 수동으로 등록
package com.kh.finalkh11.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class EncryptConfiguration {
@Bean
public PasswordEncoder encoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
// MemberRepoImpl을 수정했다.
package com.kh.finalkh11.repo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import com.kh.finalkh11.dto.MemberDto;
import com.kh.finalkh11.vo.AdminPaginationVO;
@Repository
public class MemberRepoImpl implements MemberRepo{
@Autowired
private SqlSession sqlSession;
@Autowired
private PasswordEncoder encoder;
@Override //암호화된 회원가입
public void insert(MemberDto memberDto) {
PasswordEncoder encoder = new BCryptPasswordEncoder();
String encrypt = encoder.encode(memberDto.getMemberPw());
memberDto.setMemberPw(encrypt);
sqlSession.insert("member.memberJoin",memberDto);
}
@Override
public boolean delete(String memberId) {
PasswordEncoder encoder = new BCryptPasswordEncoder();
String encrypt = encoder.encode(memberId);
return sqlSession.delete("member.memberDelete",memberId)>0;
}
@Override
public boolean changePw(String memberId, String memberPw) {// String memberPw(변경할 비밀번호)
Map<String, Object> param = new HashMap<>();
PasswordEncoder encoder = new BCryptPasswordEncoder();
String encrypt = encoder.encode((CharSequence)memberPw);
param.put("memberId", memberId);
param.put("memberPw", encrypt);
int changeResult = sqlSession.update("member.changePw", param);
return changeResult > 0;
}
}
<MemberController도 수정>
package com.kh.finalkh11.controller;
import java.io.IOException;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.kh.finalkh11.component.RandomComponent;
import com.kh.finalkh11.constant.SessionConstant;
import com.kh.finalkh11.dto.ImgDto;
import com.kh.finalkh11.dto.MemberDto;
import com.kh.finalkh11.dto.PaymentDto;
import com.kh.finalkh11.repo.ImgRepo;
import com.kh.finalkh11.repo.MemberRepo;
import com.kh.finalkh11.repo.PaymentRepo;
import com.kh.finalkh11.repo.ReserveRepo;
import com.kh.finalkh11.service.KakaoPayService;
import com.kh.finalkh11.service.MemberService;
import com.kh.finalkh11.vo.KakaoPayCancelRequestVO;
import com.kh.finalkh11.vo.KakaoPayCancelResponseVO;
@Controller
@RequestMapping("/member")
public class MemberController {
@Autowired
private MemberRepo memberRepo;
@Autowired
private ImgRepo imgRepo;
@Autowired
private MemberService memberService;
@Autowired //메일
private RandomComponent randomComponent;
@Autowired //메일
private JavaMailSender sender;
@Autowired
private PasswordEncoder encoder;
@Autowired
private KakaoPayService kakaoPayService;
@Autowired
private PaymentRepo paymentRepo;
@Autowired
private ReserveRepo reserveRepo;
//로그인
@GetMapping("/login")
public String login() {
return "member/login";
}
@PostMapping("/login")
public String login(
HttpSession session,
@ModelAttribute MemberDto userDto,
@RequestParam String memberId,
@RequestParam(value = "checked", required = false) boolean isChecked,
RedirectAttributes attr,
HttpServletResponse response) {
// 사용자가 체크박스를 선택한 경우에만 쿠키에 아이디를 저장합니다.
if (isChecked) {
Cookie cookie = new Cookie("saveId", userDto.getMemberId());
cookie.setMaxAge(30 * 24 * 60 * 60); // 쿠키 유효기간을 30일로 설정합니다.
cookie.setPath("/");
response.addCookie(cookie);
}
else {
// 체크박스를 선택하지 않은 경우, 기존에 저장된 쿠키를 삭제합니다.
Cookie cookie = new Cookie("saveId", "");
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
}
//userDto = 사용자가 입력한 dto, findDto = 찾은 dto
//로그인 검사 : 아이디 찾고, 비밀번호 일치 비교
MemberDto findDto = memberRepo.selectOne(userDto.getMemberId());
//존재하지 않는 아이디라면 -> redirect(get방식이여서 login페이지로 이동가능)
if(findDto == null) {
attr.addAttribute("mode","error");
return "redirect:login";
}
if(!encoder.matches(userDto.getMemberPw(), findDto.getMemberPw())) { //암호화된 로그인
//encoder.matches() 메서드는 주어진 두 개의 비밀번호가 일치하는지 여부를 확인
//만약 두 비밀번호가 일치한다면, matches() 메서드는 true를 반환
attr.addAttribute("mode","error");
return "redirect:login";
}
//로그인에 성공한 경우 session에 추가
session.setAttribute(SessionConstant.memberId, findDto.getMemberId());
session.setAttribute(SessionConstant.memberLevel, findDto.getMemberLevel());
session.setAttribute("memberName", findDto.getMemberName());
return "redirect:/matchBoard/list";//메인페이지로 이동
}
////////////////////////////////////////////////////////////////////////////////////////////
//회원 탈퇴
@GetMapping("/exit")
public String exit(HttpSession session) {
return "member/exit";
}
@PostMapping("/exit")
public String exit(
HttpSession session, //회원정보가 저장되어 있는 세션 객체
@RequestParam String memberPw,//사용자가 입력한 비밀번호
RedirectAttributes attr//리다이렉트 시 정보를 추가하기 위한 객체
) {
String memberId = (String) session.getAttribute(SessionConstant.memberId);
MemberDto memberDto = memberRepo.selectOne(memberId);
boolean isMatched = encoder.matches(memberPw, memberDto.getMemberPw());
//비밀번호가 일치하지 않는다면 → 비밀번호 입력 페이지로 되돌린다
if(!isMatched) {
attr.addAttribute("mode", "error");
return "redirect:exit";
}
//비밀번호가 일치한다면 → 회원탈퇴 + 로그아웃
memberRepo.delete(memberId);
session.removeAttribute(SessionConstant.memberId); //session은 브라우저 전용 데이터저장박스
session.removeAttribute(SessionConstant.memberLevel);
return "redirect:exitFinish";
}
@GetMapping("/exitFinish")
public String exitFinish() {
return "member/exitFinish";
}
////////////////////////////////////////////////////////////////////////////////////////////
@GetMapping("/findPw")//비밀번호 찾기
public String findPw() {
return "member/findPw";
}
@PostMapping("/findPw")
public String findPw(@ModelAttribute MemberDto memberDto,
RedirectAttributes attr,
@RequestParam String memberId,
@RequestParam String memberEmail) {
try {
MemberDto userDto = memberRepo.selectOne(memberId);
if (userDto == null || !userDto.getMemberEmail().equals(memberEmail)) {
throw new IllegalArgumentException("일치하는 정보가 없습니다.");
}
String userEmail = userDto.getMemberEmail();
String userId = userDto.getMemberId();
String temporaryPw = randomComponent.generateString(10);
if(memberId.equals(userId) && memberEmail.equals(userEmail)) {
//[1] 메세지 생성 - sender에게 생성하도록 지시
MimeMessage message = sender.createMimeMessage();
//[2] 메세지 헬퍼 생성 - 각종 처리를 쉽게 할 수 있도록 도와주는 역할
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
//[3] 헬퍼에 정보 설정
helper.setTo(memberEmail);
helper.setSubject("[MATCH-UP] 임시 비밀번호 발급");
// HTML 내용 작성
String htmlContent = "<p>발급된 임시 비밀번호는 <strong>" + temporaryPw + "</strong>입니다. 로그인 후 비밀번호를 반드시 변경해주시길 바랍니다.</p>";
helper.setText(htmlContent, true);
//[4] 전송
sender.send(message);
// 비밀번호 변경
memberRepo.changePw(memberId, temporaryPw);
}
}
catch(Exception e) {
attr.addAttribute("mode", "error");
return "redirect:findPw";
}
return "member/findResult";
}
////////////////////////////////////////////////////////////////////////////////////////////
@GetMapping("/password") //비밀번호 변경
public String password() {
return "member/password";
}
@PostMapping("/password")
public String password(@RequestParam String currentPw,
@RequestParam String newPw,
RedirectAttributes attr, HttpSession session) {
String memberId = (String) session.getAttribute(SessionConstant.memberId);
MemberDto dto = memberRepo.selectOne(memberId);
String memberPw = dto.getMemberPw();
PasswordEncoder encoder = new BCryptPasswordEncoder();
boolean isMatched = encoder.matches(currentPw, memberPw);
if(!isMatched) {
attr.addAttribute("mode","error");
return "redirect:password";
}
memberRepo.changePw(memberId, newPw);
return "redirect:passwordFinish";
}
@GetMapping("/passwordFinish")
public String passwordFinish() {
return "member/passwordFinish";
}
}
* 암호화
- 암호화의 종류에는 단방향,양방향 암호화가 존재한다.
- 가져가도 의미가 없도록 만드는 것이 웹에서 암호화 하는 기본 원리이다.
- 현재 위 코드에서는 단방향 암호화를 사용했다.
- 단방향 암호화 : 암호화는 가능한데 복호화(복구)가 안되는 암호화
- - 복호화는 안되어도 비교는 가능해야한다.
- - 똑같은 값을 암호화하면 판정 가능한 동일한 값이 나와야 한다.
- maven에서 spring-security-core 가져와서, pom.xml에 암호화 모듈 의존성 추가하고, PasswordEncoder encoder = new BCryptPasswordEncoder(); 생성자를 생성해서 객체를 호출하여 사용
'Project > 매치업(풋살 매칭 사이트)' 카테고리의 다른 글
최종 코드 (0) | 2023.07.17 |
---|---|
로그아웃, 회원탈퇴 구현 (0) | 2023.07.17 |
Final Project - 풋살 팀 매칭 사이트(Match-Up) (0) | 2023.07.01 |
+이메일 중복검사, 프로필 이미지 올리기 (0) | 2023.05.17 |
회원가입 페이지 구현 (0) | 2023.05.15 |